PKCS#8
#cryptxdevquotes: The allocation for this structure needs more space than exists on the calculator. How is this even working? - Anthony Cagliano
Module Functionality
Provides functions for the import of PKCS#8-encoded public and private keys that can be used with the RSA and EC modules of this library.
PKCS stands for Public Key Cryptography Standards and specification #8 provides general key encoding guidelines for various forms of public and private keys. Because the API of this library tends to work on raw data (rather than on key structures like other libraries do), this module provides a way to deserialize PKCS#8 keyfiles such that you can access components of the key. You can also pass these public and private key structures directly to the TLS implementation (coming soon).
PKCS#8 typically encodes keydata using the following workflow:
The components of the key are encoded using ASN.1/DER. Click here for more details.
The ASN.1 structure is then encoded using Base64/PEM.
The key data is wrapped in a header/footer banner indicating the type of key. These banners may be:
-----BEGIN PUBLIC KEY----- base64-encoded public key -----END PUBLIC KEY----- -----BEGIN PRIVATE KEY----- base64-encoded private key -----END PRIVATE KEY----- -----BEGIN ENCRYPTED PRIVATE KEY----- base64-encoded encrypted private key -----END ENCRYPTED PRIVATE KEY-----
Enumerations
-
enum _pkcs8_pubkey_rsa_fields
Values:
-
enumerator PKCS8_PUBLIC_RSA_MODULUS = 0
reference to public modulus in cryptx_pkcs8_pubkey
-
enumerator PKCS8_PUBLIC_RSA_EXPONENT
reference to public exponent in cryptx_pkcs8_pubkey
-
enumerator PKCS8_PUBLIC_RSA_FIELDS
number of RSA fields in structure (for enumeration)
-
enumerator PKCS8_PUBLIC_RSA_MODULUS = 0
-
enum _pkcs8_pubkey_ec_fields
Values:
-
enumerator PKCS8_PUBLIC_EC_CURVEID = 0
reference to EC Curve ID in cryptx_pkcs8_pubkey
-
enumerator PKCS8_PUBLIC_EC_PUBKEY
reference to ECPoint public key in cryptx_pkcs8_pubkey
-
enumerator PKCS8_PUBLIC_EC_FIELDS
number of EC fields in structure (for enumeration)
-
enumerator PKCS8_PUBLIC_EC_CURVEID = 0
-
enum _pkcs8_privkey_rsa_fields
Values:
-
enumerator PKCS8_PRIVATE_RSA_VERSION = 0
reference to RSA version in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_MODULUS
reference to private modulus in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_PUBEXPONENT
reference to public exponent in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_EXPONENT
reference to private exponent in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_P
reference to P in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_Q
reference to Q in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_EXP1
reference to Exp1 in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_EXP2
reference to Exp2 in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_COEFF
reference to Coefficient in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_RSA_FIELDS
number of RSA fields in structure (for enumeration)
-
enumerator PKCS8_PRIVATE_RSA_VERSION = 0
-
enum _pkcs8_privkey_ec_fields
Values:
-
enumerator PKCS8_PRIVATE_EC_CURVEID = 0
reference to EC Curve ID in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_EC_VERSION
reference to EC version in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_EC_PRIVKEY
reference to private key in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_EC_PUBKEY
reference to public key in cryptx_pkcs8_privkey
-
enumerator PKCS8_PRIVATE_EC_FIELDS
number of EC fields in structure (for enumeration)
-
enumerator PKCS8_PRIVATE_EC_CURVEID = 0
Structures
-
struct cryptx_pkcs8_pubkey
Defines a structure for holding imported RSA or ECC public key data.
Public Members
-
bool error
deserialization status, False if no error, True if failed.
-
struct cryptx_asn1_object objectid
reference to primary object ID of object.
-
union cryptx_pkcs8_pubkey::_publickey publickey
expresses EC or RSA key data.
-
size_t len
length of raw data portion of structure.
-
uint8_t raw[]
contains dump of raw data from deserialized key.
-
union _publickey
Public Members
-
struct cryptx_asn1_object ec_fields[PKCS8_PUBLIC_EC_FIELDS]
reserve EC fields
-
struct cryptx_asn1_object rsa_fields[PKCS8_PUBLIC_RSA_FIELDS]
reserve RSA fields
-
struct cryptx_asn1_object ec_fields[PKCS8_PUBLIC_EC_FIELDS]
-
bool error
-
struct cryptx_pkcs8_privkey
Defines a structure for holding imported RSA or ECC private key data.
Public Members
-
bool error
deserialization status, False if no error, True if failed.
-
struct cryptx_asn1_object objectid
reference to primary object ID of object.
-
union cryptx_pkcs8_privkey::_privatekey privatekey
expresses EC or RSA key data.
-
size_t len
length of raw data portion of structure.
-
uint8_t raw[]
contains dump of raw data from deserialized key.
-
union _privatekey
Public Members
-
struct cryptx_asn1_object rsa_fields[PKCS8_PRIVATE_RSA_FIELDS]
reserve RSA fields
-
struct cryptx_asn1_object ec_fields[PKCS8_PRIVATE_EC_FIELDS]
reserve EC fields
-
struct cryptx_asn1_object rsa_fields[PKCS8_PRIVATE_RSA_FIELDS]
-
bool error
Note
These structures, particularly cryptx_pkcs8_privkey, take up a lot of memory. This module uses dynamic allocation to optimize storage requirements for these structures to the best extent possible. Each structure contains a static portion which contains references to a dump of the raw data of the key and the dump section is of variable size depending on the size of the key.
Note
Passphrase-encrypted private keys are not currently supported by this library and will return an error if used for now. This may change in the future, check in or poke us on the discord.
Functions
-
struct cryptx_pkcs8_pubkey *cryptx_pkcs8_import_publickey(void *data, size_t len, void *(*malloc)(size_t))
Attempts to import a PKCS#8-encoded public key for RSA or ECC.
- Parameters
data – Pointer to PKCS#8-encoded key data.
len – Length of key data to import.
malloc – Pointer to toolchain malloc function.
- Returns
A malloc’d cryptx_pkcs8_pubkey structure populated with key metadata.
- Returns
NULL if arguments invalid or allocation failure.
- Returns
The error field of the structure set to True if a deserialization error occurred.
-
struct cryptx_pkcs8_privkey *cryptx_pkcs8_import_privatekey(void *data, size_t len, void *(*malloc)(size_t))
Attempts to import a PKCS#8-encoded private key for RSA or ECC.
- Parameters
data – Pointer to PKCS#8-encoded key data.
len – Length of key data to import.
malloc – Pointer to toolchain malloc function.
- Returns
A malloc’d cryptx_pkcs8_privkey structure populated with key metadata.
- Returns
NULL if arguments invalid or allocation failure.
- Returns
The error field of the structure set to True if a deserialization error occurred.
-
void cryptx_pkcs8_free_publickey(struct cryptx_pkcs8_pubkey *pk, void (*free)(void*))
Erases a PKCS#8 public key structure returned by cryptx_pkcs8_import_publickey and then frees the allocated memory.
- Parameters
pk – Pointer to a PKCS#8 public key structure.
free – Pointer to toolchain free function.
-
void cryptx_pkcs8_free_privatekey(struct cryptx_pkcs8_privkey *pk, void (*free)(void*))
Erases a PKCS#8 private key structure returned by cryptx_pkcs8_import_privatekey and then frees the allocated memory.
- Parameters
pk – Pointer to a PKCS#8 private key structure.
free – Pointer to toolchain free function.
Note
Remember to call the corresponding free method for any structure allocated with the module or you may wind up with memory leaks.
You can import your keyfiles like so:
// assume that you have generated a keypair using openssl or some similar software
// then converted to appvars 'MyPub' and 'MyPriv' using convbin,
// then transferred both to your calculator
char *pubkey_fname = "MyPub";
char *privkey_fname = "MyPriv";
uint8_t fp;
uint8_t *key_data;
size_t key_len;
// load pubkey from file (requires FILEIOC library)
if(!(fp = ti_Open(pubkey_fname, "r"))) {
printf("File IO Error");
exit(1);
}
key_data = ti_GetDataPtr(fp);
key_len = ti_GetSize(fp);
ti_Close(fp);
cryptx_pkcs8_pubkey *pub = cryptx_pkcs8_import_publickey(key_data, key_len, malloc);
if(!pub){
printf("Alloc error!");
exit(2);
}
if(pub->error) {
printf("Deserialization error!");
exit(3);
}
// load pubkey from file (requires FILEIOC library)
if(!(fp = ti_Open(privkey_fname, "r"))) {
printf("File IO Error");
exit(1);
}
key_data = ti_GetDataPtr(fp);
key_len = ti_GetSize(fp);
ti_Close(fp);
cryptx_pkcs8_privkey *priv = cryptx_pkcs8_import_privatekey(key_data, key_len, malloc);
if(!priv){
printf("Alloc error!");
exit(2);
}
if(priv->error) {
printf("Deserialization error!");
exit(3);
}
// these structs can be passed directly to the TLS implementation (coming soon)
// or the members can be accessed directly for advanced usage.
Additional Info
PKCS#8 Specification
This section details the PKCS#8 encoding format for public and private key files.
PublicKeyInfo ::= SEQUENCE {
algorithm ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
PublicKey BIT STRING
}
PrivateKeyInfo ::= SEQUENCE {
version Version,
algorithm ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
PrivateKey BIT STRING
}
EncryptedPrivateKeyInfo ::= SEQUENCE {
encryptionAlgorithm ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameters ANY DEFINED BY algorithm OPTIONAL
}
encryptedData ::= OCTET STRING (encrypts PrivateKeyInfo)
}
For some key formats the PublicKey field further encodes a structure from a different standard. This is true for all CryptX use cases of these keys.
-- from PKCS#1, src: rfc3447 A.1.1
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER, -- e
}
-- from PKCS#1, src: rfc3447 A.1.2
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
-- from SECG1, src: rfc5915 1.3
ECPrivateKey ::= SEQUENCE {
version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
privateKey OCTET STRING,
parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
publicKey [1] BIT STRING OPTIONAL
}
-- from SECG1, src: rfc5915 2.2
ECPublicKey ::= ECPoint ::= OCTET STRING
-- first octet of key is 0x04 for uncompressed or 0x03 or 0x02 for compressed
Object Identifier Reference
This section lists object identifiers for algorithms supported by this library. Developers should generally never need to use these as the library should handle it internally, but if you need them for other projects or even for custom implementations, here they are.
Bear in mind that while this module can successfully import objects for most algorithm types, only the ones listed below can actually be USED by the library.
-
static const uint8_t cryptx_pkcs8_objectid_rsa[]
Encoded Object Identifier for RSA.
-
static const uint8_t cryptx_pkcs8_objectid_ec[]
Encoded Object Identifier for ECC.
-
static const uint8_t cryptx_pkcs8_curveid_sect233k1[]
Encoded Object Identifier for SECT233k1.