Merge pull request #135 from ARMmbed/export_sanity_tests
Document asymmetric key export formats
This commit is contained in:
commit
c0454a7369
4 changed files with 777 additions and 145 deletions
|
@ -360,17 +360,71 @@ typedef uint32_t psa_key_type_t;
|
|||
*/
|
||||
#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000)
|
||||
|
||||
#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7e000000)
|
||||
#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000)
|
||||
#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000)
|
||||
#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000)
|
||||
#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000)
|
||||
#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000)
|
||||
|
||||
#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000)
|
||||
|
||||
/** Whether a key type is vendor-defined. */
|
||||
#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \
|
||||
(((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0)
|
||||
|
||||
/** Whether a key type is an unstructured array of bytes.
|
||||
*
|
||||
* This encompasses both symmetric keys and non-key data.
|
||||
*/
|
||||
#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \
|
||||
(((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \
|
||||
PSA_KEY_TYPE_CATEGORY_SYMMETRIC)
|
||||
|
||||
/** Whether a key type is asymmetric: either a key pair or a public key. */
|
||||
#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \
|
||||
(((type) & PSA_KEY_TYPE_CATEGORY_MASK \
|
||||
& ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \
|
||||
PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY)
|
||||
/** Whether a key type is the public part of a key pair. */
|
||||
#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \
|
||||
(((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY)
|
||||
/** Whether a key type is a key pair containing a private part and a public
|
||||
* part. */
|
||||
#define PSA_KEY_TYPE_IS_KEYPAIR(type) \
|
||||
(((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR)
|
||||
/** The key pair type corresponding to a public key type.
|
||||
*
|
||||
* You may also pass a key pair type as \p type, it will be left unchanged.
|
||||
*
|
||||
* \param type A public key type or key pair type.
|
||||
*
|
||||
* \return The corresponding key pair type.
|
||||
* If \p type is not a public key or a key pair,
|
||||
* the return value is undefined.
|
||||
*/
|
||||
#define PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY(type) \
|
||||
((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR)
|
||||
/** The public key type corresponding to a key pair type.
|
||||
*
|
||||
* You may also pass a key pair type as \p type, it will be left unchanged.
|
||||
*
|
||||
* \param type A public key type or key pair type.
|
||||
*
|
||||
* \return The corresponding public key type.
|
||||
* If \p type is not a public key or a key pair,
|
||||
* the return value is undefined.
|
||||
*/
|
||||
#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) \
|
||||
((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR)
|
||||
/** Whether a key type is an RSA key (pair or public-only). */
|
||||
#define PSA_KEY_TYPE_IS_RSA(type) \
|
||||
(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY)
|
||||
|
||||
/** Raw data.
|
||||
*
|
||||
* A "key" of this type cannot be used for any cryptographic operation.
|
||||
* Applications may use this type to store arbitrary data in the keystore. */
|
||||
#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x02000000)
|
||||
|
||||
#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x04000000)
|
||||
#define PSA_KEY_TYPE_CATEGORY_ASYMMETRIC ((psa_key_type_t)0x06000000)
|
||||
#define PSA_KEY_TYPE_PAIR_FLAG ((psa_key_type_t)0x01000000)
|
||||
#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001)
|
||||
|
||||
/** HMAC key.
|
||||
*
|
||||
|
@ -380,21 +434,21 @@ typedef uint32_t psa_key_type_t;
|
|||
* HMAC keys should generally have the same size as the underlying hash.
|
||||
* This size can be calculated with #PSA_HASH_SIZE(\c alg) where
|
||||
* \c alg is the HMAC algorithm or the underlying hash algorithm. */
|
||||
#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x02000001)
|
||||
#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000)
|
||||
|
||||
/** A secret for key derivation.
|
||||
*
|
||||
* The key policy determines which key derivation algorithm the key
|
||||
* can be used for.
|
||||
*/
|
||||
#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x02000101)
|
||||
#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000)
|
||||
|
||||
/** Key for an cipher, AEAD or MAC algorithm based on the AES block cipher.
|
||||
*
|
||||
* The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or
|
||||
* 32 bytes (AES-256).
|
||||
*/
|
||||
#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x04000001)
|
||||
#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001)
|
||||
|
||||
/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).
|
||||
*
|
||||
|
@ -405,30 +459,30 @@ typedef uint32_t psa_key_type_t;
|
|||
* deprecated and should only be used to decrypt legacy data. 3-key 3DES
|
||||
* is weak and deprecated and should only be used in legacy protocols.
|
||||
*/
|
||||
#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x04000002)
|
||||
#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002)
|
||||
|
||||
/** Key for an cipher, AEAD or MAC algorithm based on the
|
||||
* Camellia block cipher. */
|
||||
#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x04000003)
|
||||
#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003)
|
||||
|
||||
/** Key for the RC4 stream cipher.
|
||||
*
|
||||
* Note that RC4 is weak and deprecated and should only be used in
|
||||
* legacy protocols. */
|
||||
#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x04000004)
|
||||
#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004)
|
||||
|
||||
/** RSA public key. */
|
||||
#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x06010000)
|
||||
#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000)
|
||||
/** RSA key pair (private and public key). */
|
||||
#define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x07010000)
|
||||
#define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x70010000)
|
||||
|
||||
/** DSA public key. */
|
||||
#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x06020000)
|
||||
#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000)
|
||||
/** DSA key pair (private and public key). */
|
||||
#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x07020000)
|
||||
#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x70020000)
|
||||
|
||||
#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x06030000)
|
||||
#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x07030000)
|
||||
#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000)
|
||||
#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x70030000)
|
||||
#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff)
|
||||
/** Elliptic curve key pair. */
|
||||
#define PSA_KEY_TYPE_ECC_KEYPAIR(curve) \
|
||||
|
@ -437,32 +491,6 @@ typedef uint32_t psa_key_type_t;
|
|||
#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \
|
||||
(PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve))
|
||||
|
||||
/** Whether a key type is vendor-defined. */
|
||||
#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \
|
||||
(((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0)
|
||||
|
||||
/** Whether a key type is asymmetric: either a key pair or a public key. */
|
||||
#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \
|
||||
(((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)
|
||||
/** Whether a key type is the public part of a key pair. */
|
||||
#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \
|
||||
(((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \
|
||||
PSA_KEY_TYPE_CATEGORY_ASYMMETRIC)
|
||||
/** Whether a key type is a key pair containing a private part and a public
|
||||
* part. */
|
||||
#define PSA_KEY_TYPE_IS_KEYPAIR(type) \
|
||||
(((type) & (PSA_KEY_TYPE_CATEGORY_MASK | PSA_KEY_TYPE_PAIR_FLAG)) == \
|
||||
(PSA_KEY_TYPE_CATEGORY_ASYMMETRIC | PSA_KEY_TYPE_PAIR_FLAG))
|
||||
/** The key pair type corresponding to a public key type. */
|
||||
#define PSA_KEY_TYPE_KEYPAIR_OF_PUBLIC_KEY(type) \
|
||||
((type) | PSA_KEY_TYPE_PAIR_FLAG)
|
||||
/** The public key type corresponding to a key pair type. */
|
||||
#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) \
|
||||
((type) & ~PSA_KEY_TYPE_PAIR_FLAG)
|
||||
/** Whether a key type is an RSA key (pair or public-only). */
|
||||
#define PSA_KEY_TYPE_IS_RSA(type) \
|
||||
(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY)
|
||||
|
||||
/** Whether a key type is an elliptic curve key (pair or public-only). */
|
||||
#define PSA_KEY_TYPE_IS_ECC(type) \
|
||||
((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) & \
|
||||
|
@ -1159,10 +1187,54 @@ psa_status_t psa_get_key_information(psa_key_slot_t key,
|
|||
* - For Triple-DES, the format is the concatenation of the
|
||||
* two or three DES keys.
|
||||
* - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEYPAIR), the format
|
||||
* is the non-encrypted DER representation defined by PKCS\#1 (RFC 8017)
|
||||
* as RSAPrivateKey.
|
||||
* - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the format
|
||||
* is the DER representation defined by RFC 5280 as SubjectPublicKeyInfo.
|
||||
* is the non-encrypted DER encoding of the representation defined by
|
||||
* PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0.
|
||||
* ```
|
||||
* RSAPrivateKey ::= SEQUENCE {
|
||||
* version INTEGER, -- must be 0
|
||||
* 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
|
||||
* }
|
||||
* ```
|
||||
* - For DSA private keys (#PSA_KEY_TYPE_DSA_KEYPAIR), the format
|
||||
* is the non-encrypted DER encoding of the representation used by
|
||||
* OpenSSL and OpenSSH, whose structure is described in ASN.1 as follows:
|
||||
* ```
|
||||
* DSAPrivateKey ::= SEQUENCE {
|
||||
* version INTEGER, -- must be 0
|
||||
* prime INTEGER, -- p
|
||||
* subprime INTEGER, -- q
|
||||
* generator INTEGER, -- g
|
||||
* public INTEGER, -- y
|
||||
* private INTEGER, -- x
|
||||
* }
|
||||
* ```
|
||||
* - For elliptic curve key pairs (key types for which
|
||||
* #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is the
|
||||
* non-encrypted DER encoding of the representation defined by RFC 5915 as
|
||||
* `ECPrivateKey`, version 1. The `ECParameters` field must be a
|
||||
* `namedCurve` OID as specified in RFC 5480 §2.1.1.1. The public key
|
||||
* must be present and must be an `ECPoint` in the same format
|
||||
* (uncompressed variant) an ECC public key of the
|
||||
* corresponding type exported with psa_export_public_key().
|
||||
* ```
|
||||
* ECPrivateKey ::= SEQUENCE {
|
||||
* version INTEGER, -- must be 1
|
||||
* privateKey OCTET STRING,
|
||||
* -- `ceiling(log2(n)/8)`-byte string, big endian,
|
||||
* -- where n is the order of the curve.
|
||||
* parameters [0] IMPLICIT ECParameters {{ namedCurve }}, -- mandatory
|
||||
* publicKey [1] IMPLICIT BIT STRING -- mandatory
|
||||
* }
|
||||
* ```
|
||||
* - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is
|
||||
* true), the format is the same as for psa_export_public_key().
|
||||
*
|
||||
* \param key Slot whose content is to be exported. This must
|
||||
* be an occupied key slot.
|
||||
|
@ -1175,6 +1247,12 @@ psa_status_t psa_get_key_information(psa_key_slot_t key,
|
|||
* \retval #PSA_ERROR_EMPTY_SLOT
|
||||
* \retval #PSA_ERROR_NOT_PERMITTED
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p data buffer is too small. You can determine a
|
||||
* sufficient buffer size by calling
|
||||
* #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits)
|
||||
* where \c type is the key type
|
||||
* and \c bits is the key size in bits.
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_TAMPERING_DETECTED
|
||||
|
@ -1190,11 +1268,70 @@ psa_status_t psa_export_key(psa_key_slot_t key,
|
|||
* The output of this function can be passed to psa_import_key() to
|
||||
* create an object that is equivalent to the public key.
|
||||
*
|
||||
* For standard key types, the output format is as follows:
|
||||
* The format is the DER representation defined by RFC 5280 as
|
||||
* `SubjectPublicKeyInfo`, with the `subjectPublicKey` format
|
||||
* specified below.
|
||||
* ```
|
||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING }
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL }
|
||||
* ```
|
||||
*
|
||||
* - For RSA keys (#PSA_KEY_TYPE_RSA_KEYPAIR or #PSA_KEY_TYPE_RSA_PUBLIC_KEY),
|
||||
* the format is the DER representation of the public key defined by RFC 5280
|
||||
* as SubjectPublicKeyInfo.
|
||||
* - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY),
|
||||
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.1 as
|
||||
* `RSAPublicKey`,
|
||||
* with the OID `rsaEncryption`,
|
||||
* and with the parameters `NULL`.
|
||||
* ```
|
||||
* pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
|
||||
* rsadsi(113549) pkcs(1) 1 }
|
||||
* rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 }
|
||||
*
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER } -- e
|
||||
* ```
|
||||
* - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY),
|
||||
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.2 as
|
||||
* `DSAPublicKey`,
|
||||
* with the OID `id-dsa`,
|
||||
* and with the parameters `DSS-Parms`.
|
||||
* ```
|
||||
* id-dsa OBJECT IDENTIFIER ::= {
|
||||
* iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 }
|
||||
*
|
||||
* Dss-Parms ::= SEQUENCE {
|
||||
* p INTEGER,
|
||||
* q INTEGER,
|
||||
* g INTEGER }
|
||||
* DSAPublicKey ::= INTEGER -- public key, Y
|
||||
* ```
|
||||
* - For elliptic curve public keys (key types for which
|
||||
* #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true),
|
||||
* the `subjectPublicKey` format is defined by RFC 3279 §2.3.5 as
|
||||
* `ECPoint`, which contains the uncompressed
|
||||
* representation defined by SEC1 §2.3.3.
|
||||
* The OID is `id-ecPublicKey`,
|
||||
* and the parameters must be given as a `namedCurve` OID as specified in
|
||||
* RFC 5480 §2.1.1.1 or other applicable standards.
|
||||
* ```
|
||||
* ansi-X9-62 OBJECT IDENTIFIER ::=
|
||||
* { iso(1) member-body(2) us(840) 10045 }
|
||||
* id-public-key-type OBJECT IDENTIFIER ::= { ansi-X9.62 2 }
|
||||
* id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 }
|
||||
*
|
||||
* ECPoint ::= ...
|
||||
* -- first 8 bits: 0x04;
|
||||
* -- then x_P as an n-bit string, big endian;
|
||||
* -- then y_P as a n-bit string, big endian,
|
||||
* -- where n is the order of the curve.
|
||||
*
|
||||
* EcpkParameters ::= CHOICE { -- other choices are not allowed
|
||||
* namedCurve OBJECT IDENTIFIER }
|
||||
* ```
|
||||
*
|
||||
* \param key Slot whose content is to be exported. This must
|
||||
* be an occupied key slot.
|
||||
|
@ -1206,6 +1343,14 @@ psa_status_t psa_export_key(psa_key_slot_t key,
|
|||
* \retval #PSA_SUCCESS
|
||||
* \retval #PSA_ERROR_EMPTY_SLOT
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The key is neither a public key nor a key pair.
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
|
||||
* The size of the \p data buffer is too small. You can determine a
|
||||
* sufficient buffer size by calling
|
||||
* #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(\c type), \c bits)
|
||||
* where \c type is the key type
|
||||
* and \c bits is the key size in bits.
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_TAMPERING_DETECTED
|
||||
|
|
|
@ -305,4 +305,212 @@
|
|||
PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \
|
||||
0)
|
||||
|
||||
/* Maximum size of the ASN.1 encoding of an INTEGER with the specified
|
||||
* number of bits.
|
||||
*
|
||||
* This definition assumes that bits <= 2^19 - 9 so that the length field
|
||||
* is at most 3 bytes. The length of the encoding is the length of the
|
||||
* bit string padded to a whole number of bytes plus:
|
||||
* - 1 type byte;
|
||||
* - 1 to 3 length bytes;
|
||||
* - 0 to 1 bytes of leading 0 due to the sign bit.
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \
|
||||
((bits) / 8 + 5)
|
||||
|
||||
/* Maximum size of the export encoding of an RSA public key.
|
||||
* Assumes that the public exponent is less than 2^32.
|
||||
*
|
||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING } -- contains RSAPublicKey
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters NULL }
|
||||
* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER } -- e
|
||||
*
|
||||
* - 3 * 4 bytes of SEQUENCE overhead;
|
||||
* - 1 + 1 + 9 bytes of algorithm (RSA OID);
|
||||
* - 2 bytes of NULL;
|
||||
* - 4 bytes of BIT STRING overhead;
|
||||
* - n : INTEGER;
|
||||
* - 7 bytes for the public exponent.
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \
|
||||
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 36)
|
||||
|
||||
/* Maximum size of the export encoding of an RSA key pair.
|
||||
* Assumes thatthe public exponent is less than 2^32 and that the size
|
||||
* difference between the two primes is at most 1 bit.
|
||||
*
|
||||
* RSAPrivateKey ::= SEQUENCE {
|
||||
* version Version, -- 0
|
||||
* modulus INTEGER, -- N-bit
|
||||
* publicExponent INTEGER, -- 32-bit
|
||||
* privateExponent INTEGER, -- N-bit
|
||||
* prime1 INTEGER, -- N/2-bit
|
||||
* prime2 INTEGER, -- N/2-bit
|
||||
* exponent1 INTEGER, -- N/2-bit
|
||||
* exponent2 INTEGER, -- N/2-bit
|
||||
* coefficient INTEGER, -- N/2-bit
|
||||
* }
|
||||
*
|
||||
* - 4 bytes of SEQUENCE overhead;
|
||||
* - 3 bytes of version;
|
||||
* - 7 half-size INTEGERs plus 2 full-size INTEGERs,
|
||||
* overapproximated as 9 half-size INTEGERS;
|
||||
* - 7 bytes for the public exponent.
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_RSA_KEYPAIR_MAX_SIZE(key_bits) \
|
||||
(9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14)
|
||||
|
||||
/* Maximum size of the export encoding of a DSA public key.
|
||||
*
|
||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING } -- contains DSAPublicKey
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs
|
||||
* DSAPublicKey ::= INTEGER -- public key, Y
|
||||
*
|
||||
* - 3 * 4 bytes of SEQUENCE overhead;
|
||||
* - 1 + 1 + 7 bytes of algorithm (DSA OID);
|
||||
* - 4 bytes of BIT STRING overhead;
|
||||
* - 3 full-size INTEGERs (p, g, y);
|
||||
* - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits).
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \
|
||||
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59)
|
||||
|
||||
/* Maximum size of the export encoding of a DSA key pair.
|
||||
*
|
||||
* DSAPrivateKey ::= SEQUENCE {
|
||||
* version Version, -- 0
|
||||
* prime INTEGER, -- p
|
||||
* subprime INTEGER, -- q
|
||||
* generator INTEGER, -- g
|
||||
* public INTEGER, -- y
|
||||
* private INTEGER, -- x
|
||||
* }
|
||||
*
|
||||
* - 4 bytes of SEQUENCE overhead;
|
||||
* - 3 bytes of version;
|
||||
* - 3 full-size INTEGERs (p, g, y);
|
||||
* - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits).
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_DSA_KEYPAIR_MAX_SIZE(key_bits) \
|
||||
(PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75)
|
||||
|
||||
/* Maximum size of the export encoding of an ECC public key.
|
||||
*
|
||||
* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING } -- contains ECPoint
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters OBJECT IDENTIFIER } -- namedCurve
|
||||
* ECPoint ::= ...
|
||||
* -- first 8 bits: 0x04;
|
||||
* -- then x_P as an n-bit string, big endian;
|
||||
* -- then y_P as a n-bit string, big endian,
|
||||
* -- where n is the order of the curve.
|
||||
*
|
||||
* - 2 * 4 bytes of SEQUENCE overhead;
|
||||
* - 1 + 1 + 7 bytes of algorithm (id-ecPublicKey OID);
|
||||
* - 1 + 1 + 12 bytes of namedCurve OID;
|
||||
* - 4 bytes of BIT STRING overhead;
|
||||
* - 1 byte + 2 * point size in ECPoint.
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \
|
||||
(2 * PSA_BITS_TO_BYTES(key_bits) + 36)
|
||||
|
||||
/* Maximum size of the export encoding of an ECC key pair.
|
||||
*
|
||||
* ECPrivateKey ::= SEQUENCE {
|
||||
* version INTEGER, -- must be 1
|
||||
* privateKey OCTET STRING,
|
||||
* -- `ceiling(log2(n)/8)`-byte string, big endian,
|
||||
* -- where n is the order of the curve.
|
||||
* parameters [0] IMPLICIT ECParameters {{ NamedCurve }},
|
||||
* publicKey [1] IMPLICIT BIT STRING
|
||||
* }
|
||||
*
|
||||
* - 4 bytes of SEQUENCE overhead;
|
||||
* - 1 * point size in privateKey
|
||||
* - 1 + 1 + 12 bytes of namedCurve OID;
|
||||
* - 4 bytes of BIT STRING overhead;
|
||||
* - public key as for #PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE.
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_ECC_KEYPAIR_MAX_SIZE(key_bits) \
|
||||
(3 * PSA_BITS_TO_BYTES(key_bits) + 56)
|
||||
|
||||
/** Safe output buffer size for psa_export_key() or psa_export_public_key().
|
||||
*
|
||||
* This macro returns a compile-time constant if its arguments are
|
||||
* compile-time constants.
|
||||
*
|
||||
* \warning This function may call its arguments multiple times or
|
||||
* zero times, so you should not pass arguments that contain
|
||||
* side effects.
|
||||
*
|
||||
* The following code illustrates how to allocate enough memory to export
|
||||
* a key by querying the key type and size at runtime.
|
||||
* \code{c}
|
||||
* psa_key_type_t key_type;
|
||||
* size_t key_bits;
|
||||
* psa_status_t status;
|
||||
* status = psa_get_key_information(key, &key_type, &key_bits);
|
||||
* if (status != PSA_SUCCESS) handle_error(...);
|
||||
* size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits);
|
||||
* unsigned char *buffer = malloc(buffer_size);
|
||||
* if (buffer != NULL) handle_error(...);
|
||||
* size_t buffer_length;
|
||||
* status = psa_export_key(key, buffer, buffer_size, &buffer_length);
|
||||
* if (status != PSA_SUCCESS) handle_error(...);
|
||||
* \endcode
|
||||
*
|
||||
* For psa_export_public_key(), calculate the buffer size from the
|
||||
* public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR
|
||||
* to convert a key pair type to the corresponding public key type.
|
||||
* \code{c}
|
||||
* psa_key_type_t key_type;
|
||||
* size_t key_bits;
|
||||
* psa_status_t status;
|
||||
* status = psa_get_key_information(key, &key_type, &key_bits);
|
||||
* if (status != PSA_SUCCESS) handle_error(...);
|
||||
* psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(key_type);
|
||||
* size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits);
|
||||
* unsigned char *buffer = malloc(buffer_size);
|
||||
* if (buffer != NULL) handle_error(...);
|
||||
* size_t buffer_length;
|
||||
* status = psa_export_public_key(key, buffer, buffer_size, &buffer_length);
|
||||
* if (status != PSA_SUCCESS) handle_error(...);
|
||||
* \endcode
|
||||
*
|
||||
* \param key_type A supported key type.
|
||||
* \param key_bits The size of the key in bits.
|
||||
*
|
||||
* \return If the parameters are valid and supported, return
|
||||
* a buffer size in bytes that guarantees that
|
||||
* psa_asymmetric_sign() will not fail with
|
||||
* #PSA_ERROR_BUFFER_TOO_SMALL.
|
||||
* If the parameters are a valid combination that is not supported
|
||||
* by the implementation, this macro either shall return either a
|
||||
* sensible size or 0.
|
||||
* If the parameters are not valid, the
|
||||
* return value is unspecified.
|
||||
*/
|
||||
#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \
|
||||
(PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \
|
||||
(key_type) == PSA_KEY_TYPE_RSA_KEYPAIR ? PSA_KEY_EXPORT_RSA_KEYPAIR_MAX_SIZE(key_bits) : \
|
||||
(key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \
|
||||
(key_type) == PSA_KEY_TYPE_DSA_KEYPAIR ? PSA_KEY_EXPORT_DSA_KEYPAIR_MAX_SIZE(key_bits) : \
|
||||
(key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \
|
||||
PSA_KEY_TYPE_IS_ECC_KEYPAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEYPAIR_MAX_SIZE(key_bits) : \
|
||||
PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \
|
||||
0)
|
||||
|
||||
#endif /* PSA_CRYPTO_SIZES_H */
|
||||
|
|
|
@ -135,9 +135,7 @@ typedef struct
|
|||
|
||||
static int key_type_is_raw_bytes( psa_key_type_t type )
|
||||
{
|
||||
psa_key_type_t category = type & PSA_KEY_TYPE_CATEGORY_MASK;
|
||||
return( category == PSA_KEY_TYPE_RAW_DATA ||
|
||||
category == PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
|
||||
return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) );
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
#include "spm/psa_defs.h"
|
||||
#endif
|
||||
|
||||
#include "mbedtls/asn1.h"
|
||||
#include "mbedtls/asn1write.h"
|
||||
#include "mbedtls/oid.h"
|
||||
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
|
||||
|
@ -38,13 +41,6 @@ static int mem_is_zero( void *buffer, size_t size )
|
|||
return( 1 );
|
||||
}
|
||||
|
||||
static int key_type_is_raw_bytes( psa_key_type_t type )
|
||||
{
|
||||
psa_key_type_t category = type & PSA_KEY_TYPE_CATEGORY_MASK;
|
||||
return( category == PSA_KEY_TYPE_RAW_DATA ||
|
||||
category == PSA_KEY_TYPE_CATEGORY_SYMMETRIC );
|
||||
}
|
||||
|
||||
/* Write the ASN.1 INTEGER with the value 2^(bits-1)+x backwards from *p. */
|
||||
static int asn1_write_10x( unsigned char **p,
|
||||
unsigned char *start,
|
||||
|
@ -393,6 +389,366 @@ exit:
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
static int is_oid_of_key_type( psa_key_type_t type,
|
||||
const uint8_t *oid, size_t oid_length )
|
||||
{
|
||||
const uint8_t *expected_oid = NULL;
|
||||
size_t expected_oid_length = 0;
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
if( PSA_KEY_TYPE_IS_RSA( type ) )
|
||||
{
|
||||
expected_oid = (uint8_t *) MBEDTLS_OID_PKCS1_RSA;
|
||||
expected_oid_length = sizeof( MBEDTLS_OID_PKCS1_RSA ) - 1;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if( PSA_KEY_TYPE_IS_ECC( type ) )
|
||||
{
|
||||
expected_oid = (uint8_t *) MBEDTLS_OID_EC_ALG_UNRESTRICTED;
|
||||
expected_oid_length = sizeof( MBEDTLS_OID_EC_ALG_UNRESTRICTED ) - 1;
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
{
|
||||
char message[40];
|
||||
mbedtls_snprintf( message, sizeof( message ),
|
||||
"OID not known for key type=0x%08lx",
|
||||
(unsigned long) type );
|
||||
test_fail( message, __LINE__, __FILE__ );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
TEST_ASSERT( oid_length == expected_oid_length );
|
||||
TEST_ASSERT( memcmp( oid, expected_oid, oid_length ) == 0 );
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int asn1_skip_integer( unsigned char **p, const unsigned char *end,
|
||||
size_t min_bits, size_t max_bits,
|
||||
int must_be_odd )
|
||||
{
|
||||
size_t len;
|
||||
size_t actual_bits;
|
||||
unsigned char msb;
|
||||
TEST_ASSERT( mbedtls_asn1_get_tag( p, end, &len,
|
||||
MBEDTLS_ASN1_INTEGER ) == 0 );
|
||||
/* Tolerate a slight departure from DER encoding:
|
||||
* - 0 may be represented by an empty string or a 1-byte string.
|
||||
* - The sign bit may be used as a value bit. */
|
||||
if( ( len == 1 && ( *p )[0] == 0 ) ||
|
||||
( len > 1 && ( *p )[0] == 0 && ( ( *p )[1] & 0x80 ) != 0 ) )
|
||||
{
|
||||
++( *p );
|
||||
--len;
|
||||
}
|
||||
if( min_bits == 0 && len == 0 )
|
||||
return( 1 );
|
||||
msb = ( *p )[0];
|
||||
TEST_ASSERT( msb != 0 );
|
||||
actual_bits = 8 * ( len - 1 );
|
||||
while( msb != 0 )
|
||||
{
|
||||
msb >>= 1;
|
||||
++actual_bits;
|
||||
}
|
||||
TEST_ASSERT( actual_bits >= min_bits );
|
||||
TEST_ASSERT( actual_bits <= max_bits );
|
||||
if( must_be_odd )
|
||||
TEST_ASSERT( ( ( *p )[len-1] & 1 ) != 0 );
|
||||
*p += len;
|
||||
return( 1 );
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int asn1_get_implicit_tag( unsigned char **p, const unsigned char *end,
|
||||
size_t *len,
|
||||
unsigned char n, unsigned char tag )
|
||||
{
|
||||
int ret;
|
||||
ret = mbedtls_asn1_get_tag( p, end, len,
|
||||
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
|
||||
MBEDTLS_ASN1_CONSTRUCTED | ( n ) );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
end = *p + *len;
|
||||
ret = mbedtls_asn1_get_tag( p, end, len, tag );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
if( *p + *len != end )
|
||||
return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int exported_key_sanity_check( psa_key_type_t type, size_t bits,
|
||||
uint8_t *exported, size_t exported_length )
|
||||
{
|
||||
if( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) )
|
||||
TEST_ASSERT( exported_length == ( bits + 7 ) / 8 );
|
||||
else
|
||||
TEST_ASSERT( exported_length <= PSA_KEY_EXPORT_MAX_SIZE( type, bits ) );
|
||||
|
||||
#if defined(MBEDTLS_DES_C)
|
||||
if( type == PSA_KEY_TYPE_DES )
|
||||
{
|
||||
/* Check the parity bits. */
|
||||
unsigned i;
|
||||
for( i = 0; i < bits / 8; i++ )
|
||||
{
|
||||
unsigned bit_count = 0;
|
||||
unsigned m;
|
||||
for( m = 1; m <= 0x100; m <<= 1 )
|
||||
{
|
||||
if( exported[i] & m )
|
||||
++bit_count;
|
||||
}
|
||||
TEST_ASSERT( bit_count % 2 != 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
|
||||
if( type == PSA_KEY_TYPE_RSA_KEYPAIR )
|
||||
{
|
||||
uint8_t *p = exported;
|
||||
uint8_t *end = exported + exported_length;
|
||||
size_t len;
|
||||
/* RSAPrivateKey ::= SEQUENCE {
|
||||
* version INTEGER, -- must be 0
|
||||
* 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
|
||||
* }
|
||||
*/
|
||||
TEST_ASSERT( mbedtls_asn1_get_tag( &p, end, &len,
|
||||
MBEDTLS_ASN1_SEQUENCE |
|
||||
MBEDTLS_ASN1_CONSTRUCTED ) == 0 );
|
||||
TEST_ASSERT( p + len == end );
|
||||
if( ! asn1_skip_integer( &p, end, 0, 0, 0 ) )
|
||||
goto exit;
|
||||
if( ! asn1_skip_integer( &p, end, bits, bits, 1 ) )
|
||||
goto exit;
|
||||
if( ! asn1_skip_integer( &p, end, 2, bits, 1 ) )
|
||||
goto exit;
|
||||
/* Require d to be at least half the size of n. */
|
||||
if( ! asn1_skip_integer( &p, end, bits / 2, bits, 1 ) )
|
||||
goto exit;
|
||||
/* Require p and q to be at most half the size of n, rounded up. */
|
||||
if( ! asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
|
||||
goto exit;
|
||||
if( ! asn1_skip_integer( &p, end, bits / 2, bits / 2 + 1, 1 ) )
|
||||
goto exit;
|
||||
if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
|
||||
goto exit;
|
||||
if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
|
||||
goto exit;
|
||||
if( ! asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
|
||||
goto exit;
|
||||
TEST_ASSERT( p == end );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if( PSA_KEY_TYPE_IS_ECC_KEYPAIR( type ) )
|
||||
{
|
||||
uint8_t *p = exported;
|
||||
uint8_t *end = exported + exported_length;
|
||||
size_t len;
|
||||
int version;
|
||||
/* ECPrivateKey ::= SEQUENCE {
|
||||
* version INTEGER, -- must be 1
|
||||
* privateKey OCTET STRING,
|
||||
* -- `ceiling(log_{256}(n))`-byte string, big endian,
|
||||
* -- where n is the order of the curve.
|
||||
* parameters ECParameters {{ NamedCurve }}, -- mandatory
|
||||
* publicKey BIT STRING -- mandatory
|
||||
* }
|
||||
*/
|
||||
TEST_ASSERT( mbedtls_asn1_get_tag( &p, end, &len,
|
||||
MBEDTLS_ASN1_SEQUENCE |
|
||||
MBEDTLS_ASN1_CONSTRUCTED ) == 0 );
|
||||
TEST_ASSERT( p + len == end );
|
||||
TEST_ASSERT( mbedtls_asn1_get_int( &p, end, &version ) == 0 );
|
||||
TEST_ASSERT( version == 1 );
|
||||
TEST_ASSERT( mbedtls_asn1_get_tag( &p, end, &len,
|
||||
MBEDTLS_ASN1_OCTET_STRING ) == 0 );
|
||||
/* Bug in Mbed TLS: the length of the octet string depends on the value */
|
||||
// TEST_ASSERT( len == PSA_BITS_TO_BYTES( bits ) );
|
||||
p += len;
|
||||
TEST_ASSERT( asn1_get_implicit_tag( &p, end, &len, 0,
|
||||
MBEDTLS_ASN1_OID ) == 0 );
|
||||
p += len;
|
||||
/* publicKey: ECPoint in uncompressed representation (as below) */
|
||||
TEST_ASSERT( asn1_get_implicit_tag( &p, end, &len, 1,
|
||||
MBEDTLS_ASN1_BIT_STRING ) == 0 );
|
||||
TEST_ASSERT( p + len == end );
|
||||
TEST_ASSERT( p[0] == 0 ); /* 0 unused bits in the bit string */
|
||||
++p;
|
||||
TEST_ASSERT( p + 1 + 2 * PSA_BITS_TO_BYTES( bits ) == end );
|
||||
TEST_ASSERT( p[0] == 4 );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
|
||||
if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
|
||||
{
|
||||
uint8_t *p = exported;
|
||||
uint8_t *end = exported + exported_length;
|
||||
size_t len;
|
||||
mbedtls_asn1_buf alg;
|
||||
mbedtls_asn1_buf params;
|
||||
mbedtls_asn1_bitstring bitstring;
|
||||
/* SubjectPublicKeyInfo ::= SEQUENCE {
|
||||
* algorithm AlgorithmIdentifier,
|
||||
* subjectPublicKey BIT STRING }
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL }
|
||||
*/
|
||||
TEST_ASSERT( mbedtls_asn1_get_tag( &p, end, &len,
|
||||
MBEDTLS_ASN1_SEQUENCE |
|
||||
MBEDTLS_ASN1_CONSTRUCTED ) == 0 );
|
||||
TEST_ASSERT( p + len == end );
|
||||
TEST_ASSERT( mbedtls_asn1_get_alg( &p, end, &alg, ¶ms ) == 0 );
|
||||
if( ! is_oid_of_key_type( type, alg.p, alg.len ) )
|
||||
goto exit;
|
||||
TEST_ASSERT( mbedtls_asn1_get_bitstring( &p, end, &bitstring ) == 0 );
|
||||
TEST_ASSERT( p == end );
|
||||
p = bitstring.p;
|
||||
#if defined(MBEDTLS_RSA_C)
|
||||
if( type == PSA_KEY_TYPE_RSA_PUBLIC_KEY )
|
||||
{
|
||||
/* RSAPublicKey ::= SEQUENCE {
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER } -- e
|
||||
*/
|
||||
TEST_ASSERT( bitstring.unused_bits == 0 );
|
||||
TEST_ASSERT( mbedtls_asn1_get_tag( &p, end, &len,
|
||||
MBEDTLS_ASN1_SEQUENCE |
|
||||
MBEDTLS_ASN1_CONSTRUCTED ) == 0 );
|
||||
TEST_ASSERT( p + len == end );
|
||||
if( ! asn1_skip_integer( &p, end, bits, bits, 1 ) )
|
||||
goto exit;
|
||||
if( ! asn1_skip_integer( &p, end, 2, bits, 1 ) )
|
||||
goto exit;
|
||||
TEST_ASSERT( p == end );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( type ) )
|
||||
{
|
||||
/* ECPoint ::= ...
|
||||
* -- first 8 bits: 0x04 (uncompressed representation);
|
||||
* -- then x_P as an n-bit string, big endian;
|
||||
* -- then y_P as a n-bit string, big endian,
|
||||
* -- where n is the order of the curve.
|
||||
*/
|
||||
TEST_ASSERT( bitstring.unused_bits == 0 );
|
||||
TEST_ASSERT( p + 1 + 2 * PSA_BITS_TO_BYTES( bits ) == end );
|
||||
TEST_ASSERT( p[0] == 4 );
|
||||
}
|
||||
else
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
{
|
||||
char message[40];
|
||||
mbedtls_snprintf( message, sizeof( message ),
|
||||
"No sanity check for public key type=0x%08lx",
|
||||
(unsigned long) type );
|
||||
test_fail( message, __LINE__, __FILE__ );
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
/* No sanity checks for other types */
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
|
||||
exit:
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int exercise_export_key( psa_key_slot_t slot,
|
||||
psa_key_usage_t usage )
|
||||
{
|
||||
psa_key_type_t type;
|
||||
size_t bits;
|
||||
uint8_t *exported = NULL;
|
||||
size_t exported_size = 0;
|
||||
size_t exported_length = 0;
|
||||
int ok = 0;
|
||||
|
||||
if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 )
|
||||
{
|
||||
TEST_ASSERT( psa_export_key( slot, NULL, 0, &exported_length ) ==
|
||||
PSA_ERROR_NOT_PERMITTED );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
TEST_ASSERT( psa_get_key_information( slot, &type, &bits ) == PSA_SUCCESS );
|
||||
exported_size = PSA_KEY_EXPORT_MAX_SIZE( type, bits );
|
||||
exported = mbedtls_calloc( 1, exported_size );
|
||||
TEST_ASSERT( exported != NULL );
|
||||
|
||||
TEST_ASSERT( psa_export_key( slot,
|
||||
exported, exported_size,
|
||||
&exported_length ) == PSA_SUCCESS );
|
||||
ok = exported_key_sanity_check( type, bits, exported, exported_length );
|
||||
|
||||
exit:
|
||||
mbedtls_free( exported );
|
||||
return( ok );
|
||||
}
|
||||
|
||||
static int exercise_export_public_key( psa_key_slot_t slot )
|
||||
{
|
||||
psa_key_type_t type;
|
||||
psa_key_type_t public_type;
|
||||
size_t bits;
|
||||
uint8_t *exported = NULL;
|
||||
size_t exported_size = 0;
|
||||
size_t exported_length = 0;
|
||||
int ok = 0;
|
||||
|
||||
TEST_ASSERT( psa_get_key_information( slot, &type, &bits ) == PSA_SUCCESS );
|
||||
if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( type ) )
|
||||
{
|
||||
TEST_ASSERT( psa_export_public_key( slot,
|
||||
NULL, 0, &exported_length ) ==
|
||||
PSA_ERROR_INVALID_ARGUMENT );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( type );
|
||||
exported_size = PSA_KEY_EXPORT_MAX_SIZE( public_type, bits );
|
||||
exported = mbedtls_calloc( 1, exported_size );
|
||||
TEST_ASSERT( exported != NULL );
|
||||
|
||||
TEST_ASSERT( psa_export_public_key( slot,
|
||||
exported, exported_size,
|
||||
&exported_length ) == PSA_SUCCESS );
|
||||
ok = exported_key_sanity_check( public_type, bits,
|
||||
exported, exported_length );
|
||||
|
||||
exit:
|
||||
mbedtls_free( exported );
|
||||
return( ok );
|
||||
}
|
||||
|
||||
static int exercise_key( psa_key_slot_t slot,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg )
|
||||
|
@ -421,6 +777,10 @@ static int exercise_key( psa_key_slot_t slot,
|
|||
test_fail( message, __LINE__, __FILE__ );
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
ok = ok && exercise_export_key( slot, usage );
|
||||
ok = ok && exercise_export_public_key( slot );
|
||||
|
||||
return( ok );
|
||||
}
|
||||
|
||||
|
@ -632,6 +992,9 @@ void import_export( data_t *data,
|
|||
goto destroy;
|
||||
}
|
||||
|
||||
if( ! exercise_export_key( slot, usage_arg ) )
|
||||
goto exit;
|
||||
|
||||
if( canonical_input )
|
||||
{
|
||||
TEST_ASSERT( exported_length == data->len );
|
||||
|
@ -1128,7 +1491,7 @@ exit:
|
|||
void key_lifetime( int lifetime_arg )
|
||||
{
|
||||
int key_slot = 1;
|
||||
psa_key_type_t key_type = PSA_ALG_CBC_BASE;
|
||||
psa_key_type_t key_type = PSA_KEY_TYPE_RAW_DATA;
|
||||
unsigned char key[32] = {0};
|
||||
psa_key_lifetime_t lifetime_set = lifetime_arg;
|
||||
psa_key_lifetime_t lifetime_get;
|
||||
|
@ -3056,10 +3419,6 @@ void generate_key( int type_arg,
|
|||
psa_status_t expected_status = expected_status_arg;
|
||||
psa_key_type_t got_type;
|
||||
size_t got_bits;
|
||||
unsigned char exported[616] = {0}; /* enough for a 1024-bit RSA key */
|
||||
size_t exported_length;
|
||||
psa_status_t expected_export_status =
|
||||
usage & PSA_KEY_USAGE_EXPORT ? PSA_SUCCESS : PSA_ERROR_NOT_PERMITTED;
|
||||
psa_status_t expected_info_status =
|
||||
expected_status == PSA_SUCCESS ? PSA_SUCCESS : PSA_ERROR_EMPTY_SLOT;
|
||||
psa_key_policy_t policy;
|
||||
|
@ -3083,84 +3442,6 @@ void generate_key( int type_arg,
|
|||
TEST_ASSERT( got_type == type );
|
||||
TEST_ASSERT( got_bits == bits );
|
||||
|
||||
/* Export the key */
|
||||
TEST_ASSERT( psa_export_key( slot,
|
||||
exported, sizeof( exported ),
|
||||
&exported_length ) == expected_export_status );
|
||||
if( expected_export_status == PSA_SUCCESS )
|
||||
{
|
||||
if( key_type_is_raw_bytes( type ) )
|
||||
TEST_ASSERT( exported_length == ( bits + 7 ) / 8 );
|
||||
#if defined(MBEDTLS_DES_C)
|
||||
if( type == PSA_KEY_TYPE_DES )
|
||||
{
|
||||
/* Check the parity bits. */
|
||||
unsigned i;
|
||||
for( i = 0; i < bits / 8; i++ )
|
||||
{
|
||||
unsigned bit_count = 0;
|
||||
unsigned m;
|
||||
for( m = 1; m <= 0x100; m <<= 1 )
|
||||
{
|
||||
if( exported[i] & m )
|
||||
++bit_count;
|
||||
}
|
||||
TEST_ASSERT( bit_count % 2 != 0 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
|
||||
if( type == PSA_KEY_TYPE_RSA_KEYPAIR )
|
||||
{
|
||||
/* Sanity check: does this look like the beginning of a PKCS#8
|
||||
* RSA key pair? Assumes bits is a multiple of 8. */
|
||||
size_t n_bytes = bits / 8 + 1;
|
||||
size_t n_encoded_bytes;
|
||||
unsigned char *n_end;
|
||||
TEST_ASSERT( exported_length >= 7 + ( n_bytes + 3 ) * 9 / 2 );
|
||||
TEST_ASSERT( exported[0] == 0x30 );
|
||||
TEST_ASSERT( exported[1] == 0x82 ); // assumes >=416-bit key
|
||||
TEST_ASSERT( exported[4] == 0x02 );
|
||||
TEST_ASSERT( exported[5] == 0x01 );
|
||||
TEST_ASSERT( exported[6] == 0x00 );
|
||||
TEST_ASSERT( exported[7] == 0x02 );
|
||||
n_encoded_bytes = exported[8];
|
||||
n_end = exported + 9 + n_encoded_bytes;
|
||||
if( n_encoded_bytes & 0x80 )
|
||||
{
|
||||
n_encoded_bytes = ( n_encoded_bytes & 0x7f ) << 7;
|
||||
n_encoded_bytes |= exported[9] & 0x7f;
|
||||
n_end += 1;
|
||||
}
|
||||
/* The encoding of n should start with a 0 byte since it should
|
||||
* have its high bit set. However Mbed TLS is not compliant and
|
||||
* generates an invalid, but widely tolerated, encoding of
|
||||
* positive INTEGERs with a bit size that is a multiple of 8
|
||||
* with no leading 0 byte. Accept this here. */
|
||||
TEST_ASSERT( n_bytes == n_encoded_bytes ||
|
||||
n_bytes == n_encoded_bytes + 1 );
|
||||
if( n_bytes == n_encoded_bytes )
|
||||
TEST_ASSERT( exported[n_encoded_bytes <= 127 ? 9 : 10] == 0x00 );
|
||||
/* Sanity check: e must be 3 */
|
||||
TEST_ASSERT( n_end[0] == 0x02 );
|
||||
TEST_ASSERT( n_end[1] == 0x03 );
|
||||
TEST_ASSERT( n_end[2] == 0x01 );
|
||||
TEST_ASSERT( n_end[3] == 0x00 );
|
||||
TEST_ASSERT( n_end[4] == 0x01 );
|
||||
TEST_ASSERT( n_end[5] == 0x02 );
|
||||
}
|
||||
#endif /* MBEDTLS_RSA_C */
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
if( PSA_KEY_TYPE_IS_ECC( type ) )
|
||||
{
|
||||
/* Sanity check: does this look like the beginning of a PKCS#8
|
||||
* elliptic curve key pair? */
|
||||
TEST_ASSERT( exported_length >= bits * 3 / 8 + 10 );
|
||||
TEST_ASSERT( exported[0] == 0x30 );
|
||||
}
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
}
|
||||
|
||||
/* Do something with the key according to its type and permitted usage. */
|
||||
if( ! exercise_key( slot, usage, alg ) )
|
||||
goto exit;
|
||||
|
|
Loading…
Reference in a new issue