Merge pull request #135 from ARMmbed/export_sanity_tests

Document asymmetric key export formats
This commit is contained in:
Jaeden Amero 2018-08-22 10:31:28 +01:00
commit c0454a7369
4 changed files with 777 additions and 145 deletions

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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, &params ) == 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;