.. _appendix-specdef-values:

Example macro implementations
-----------------------------

This appendix provides example implementations of the function-like macros that have specification-defined values.

.. note::
    In a future version of this specification, these example implementations will be replaced with a pseudo-code representation of the macro's computation in the macro description.

The examples here provide correct results for the valid inputs defined by each API, for an implementation that supports all of the defined algorithms and key types. An implementation can provide alternative definitions of these macros:

* If the implementation does not support all of the algorithms or key types, it can provide a simpler definition of applicable macros.
* If the implementation provides vendor-specific algorithms or key types, it needs to extend the definitions of applicable macros.

Algorithm macros
~~~~~~~~~~~~~~~~

:code:`PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg)`
    :code:`((((aead_alg) & ~0x003f0000) == 0x05400100) ? PSA_ALG_CCM : (((aead_alg) & ~0x003f0000) == 0x05400200) ? PSA_ALG_GCM : (((aead_alg) & ~0x003f0000) == 0x05000500) ? PSA_ALG_CHACHA20_POLY1305 : PSA_ALG_NONE)`

:code:`PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length)`
    :code:`((psa_algorithm_t) (((aead_alg) & ~0x003f0000) | (((tag_length) & 0x3f) << 16)))`

:code:`PSA_ALG_DETERMINISTIC_ECDSA(hash_alg)`
    :code:`((psa_algorithm_t) (0x06000700 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_ECDSA(hash_alg)`
    :code:`((psa_algorithm_t) (0x06000600 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_FULL_LENGTH_MAC(mac_alg)`
    :code:`((psa_algorithm_t) ((mac_alg) & ~0x003f0000))`

:code:`PSA_ALG_GET_HASH(alg)`
    :code:`(((alg) & 0x000000ff) == 0 ? PSA_ALG_NONE : 0x02000000 | ((alg) & 0x000000ff))`

:code:`PSA_ALG_HKDF(hash_alg)`
    :code:`((psa_algorithm_t) (0x08000100 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_HMAC(hash_alg)`
    :code:`((psa_algorithm_t) (0x03800000 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_IS_AEAD(alg)`
    :code:`(((alg) & 0x7f000000) == 0x05000000)`

:code:`PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg)`
    :code:`(((alg) & 0x7f400000) == 0x05400000)`

:code:`PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)`
    :code:`(((alg) & 0x7f000000) == 0x07000000)`

:code:`PSA_ALG_IS_BLOCK_CIPHER_MAC(alg)`
    :code:`(((alg) & 0x7fc00000) == 0x03c00000)`

:code:`PSA_ALG_IS_CIPHER(alg)`
    :code:`(((alg) & 0x7f000000) == 0x03000000)`

:code:`PSA_ALG_IS_DETERMINISTIC_ECDSA(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x06000700)`

:code:`PSA_ALG_IS_ECDH(alg)`
    :code:`(((alg) & 0x7fff0000) == 0x09020000)`

:code:`PSA_ALG_IS_ECDSA(alg)`
    :code:`(((alg) & ~0x000001ff) == 0x06000600)`

:code:`PSA_ALG_IS_FFDH(alg)`
    :code:`(((alg) & 0x7fff0000) == 0x09010000)`

:code:`PSA_ALG_IS_HASH(alg)`
    :code:`(((alg) & 0x7f000000) == 0x02000000)`

:code:`PSA_ALG_IS_HASH_AND_SIGN(alg)`
    :code:`(PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || PSA_ALG_IS_ECDSA(alg))`

:code:`PSA_ALG_IS_HKDF(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x08000100)`

:code:`PSA_ALG_IS_HMAC(alg)`
    :code:`(((alg) & 0x7fc0ff00) == 0x03800000)`

:code:`PSA_ALG_IS_KEY_AGREEMENT(alg)`
    :code:`(((alg) & 0x7f000000) == 0x09000000)`

:code:`PSA_ALG_IS_KEY_DERIVATION(alg)`
    :code:`(((alg) & 0x7f000000) == 0x08000000)`

:code:`PSA_ALG_IS_MAC(alg)`
    :code:`(((alg) & 0x7f000000) == 0x03000000)`

:code:`PSA_ALG_IS_RANDOMIZED_ECDSA(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x06000600)`

:code:`PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)`
    :code:`(((alg) & 0x7f00ffff) == 0x09000000)`

:code:`PSA_ALG_IS_RSA_OAEP(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x07000300)`

:code:`PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x06000200)`

:code:`PSA_ALG_IS_RSA_PSS(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x06000300)`

:code:`PSA_ALG_IS_SIGN(alg)`
    :code:`(((alg) & 0x7f000000) == 0x06000000)`

:code:`PSA_ALG_IS_SIGN_HASH(alg)`
    :code:`PSA_ALG_IS_SIGN(alg)`

:code:`PSA_ALG_IS_SIGN_MESSAGE(alg)`
    :code:`(PSA_ALG_IS_SIGN(alg) && (alg) != PSA_ALG_ECDSA_ANY && (alg) != PSA_ALG_RSA_PKCS1V15_SIGN_RAW)`

:code:`PSA_ALG_IS_STREAM_CIPHER(alg)`
    :code:`(((alg) & 0x7f800000) == 0x04800000)`

:code:`PSA_ALG_IS_TLS12_PRF(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x08000200)`

:code:`PSA_ALG_IS_TLS12_PSK_TO_MS(alg)`
    :code:`(((alg) & ~0x000000ff) == 0x08000300)`

:code:`PSA_ALG_IS_WILDCARD(alg)`
    :code:`(PSA_ALG_GET_HASH(alg) == PSA_ALG_HASH_ANY)`

:code:`PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg)`
    :code:`((ka_alg) | (kdf_alg))`

:code:`PSA_ALG_KEY_AGREEMENT_GET_BASE(alg)`
    :code:`((psa_algorithm_t)((alg) & 0xffff0000))`

:code:`PSA_ALG_KEY_AGREEMENT_GET_KDF(alg)`
    :code:`((psa_algorithm_t)((alg) & 0xfe00ffff))`

:code:`PSA_ALG_RSA_OAEP(hash_alg)`
    :code:`((psa_algorithm_t)(0x07000300 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg)`
    :code:`((psa_algorithm_t)(0x06000200 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_RSA_PSS(hash_alg)`
    :code:`((psa_algorithm_t)(0x06000300 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_TLS12_PRF(hash_alg)`
    :code:`((psa_algorithm_t) (0x08000200 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_TLS12_PSK_TO_MS(hash_alg)`
    :code:`((psa_algorithm_t) (0x08000300 | ((hash_alg) & 0x000000ff)))`

:code:`PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length)`
    :code:`((psa_algorithm_t) (((mac_alg) & ~0x003f0000) | (((mac_length) & 0x3f) << 16)))`

Key type macros
~~~~~~~~~~~~~~~

:code:`PSA_BLOCK_CIPHER_BLOCK_LENGTH(type)`
    :code:`(1u << (((type) >> 8) & 7))`

:code:`PSA_KEY_TYPE_DH_GET_FAMILY(type)`
    :code:`((psa_dh_family_t) ((type) & 0x00ff))`

:code:`PSA_KEY_TYPE_DH_KEY_PAIR(group)`
    :code:`((psa_key_type_t) (0x7200 | (group)))`

:code:`PSA_KEY_TYPE_DH_PUBLIC_KEY(group)`
    :code:`((psa_key_type_t) (0x4200 | (group)))`

:code:`PSA_KEY_TYPE_ECC_GET_FAMILY(type)`
    :code:`((psa_ecc_family_t) ((type) & 0x00ff))`

:code:`PSA_KEY_TYPE_ECC_KEY_PAIR(curve)`
    :code:`((psa_key_type_t) (0x7100 | (curve)))`

:code:`PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve)`
    :code:`((psa_key_type_t) (0x4100 | (curve)))`

:code:`PSA_KEY_TYPE_IS_ASYMMETRIC(type)`
    :code:`(((type) & 0x4000) == 0x4000)`

:code:`PSA_KEY_TYPE_IS_DH(type)`
    :code:`((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & 0xff00) == 0x4200)`

:code:`PSA_KEY_TYPE_IS_DH_KEY_PAIR(type)`
    :code:`(((type) & 0xff00) == 0x7200)`

:code:`PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type)`
    :code:`(((type) & 0xff00) == 0x4200)`

:code:`PSA_KEY_TYPE_IS_ECC(type)`
    :code:`((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & 0xff00) == 0x4100)`

:code:`PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)`
    :code:`(((type) & 0xff00) == 0x7100)`

:code:`PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type)`
    :code:`(((type) & 0xff00) == 0x4100)`

:code:`PSA_KEY_TYPE_IS_KEY_PAIR(type)`
    :code:`(((type) & 0x7000) == 0x7000)`

:code:`PSA_KEY_TYPE_IS_PUBLIC_KEY(type)`
    :code:`(((type) & 0x7000) == 0x4000)`

:code:`PSA_KEY_TYPE_IS_RSA(type)`
    :code:`(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == 0x4001)`

:code:`PSA_KEY_TYPE_IS_UNSTRUCTURED(type)`
    :code:`(((type) & 0x7000) == 0x1000 || ((type) & 0x7000) == 0x2000)`

:code:`PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type)`
    :code:`((psa_key_type_t) ((type) | 0x3000))`

:code:`PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type)`
    :code:`((psa_key_type_t) ((type) & ~0x3000))`

Hash suspend state macros
~~~~~~~~~~~~~~~~~~~~~~~~~

:code:`PSA_HASH_SUSPEND_HASH_STATE_FIELD_LENGTH(alg)`
    :code:`((alg)==PSA_ALG_MD2 ? 64 : (alg)==PSA_ALG_MD4 || (alg)==PSA_ALG_MD5 ? 16 : (alg)==PSA_ALG_RIPEMD160 || (alg)==PSA_ALG_SHA_1 ? 20 : (alg)==PSA_ALG_SHA_224 || (alg)==PSA_ALG_SHA_256 ? 32 : (alg)==PSA_ALG_SHA_512 || (alg)==PSA_ALG_SHA_384 || (alg)==PSA_ALG_SHA_512_256 ? 64 : 0)`

    .. Could simplify a little if allowed to return 64 for every alg value that is not MD4/MD5/RIPEMD160/SHA1/SHA223/SHA256

:code:`PSA_HASH_SUSPEND_INPUT_LENGTH_FIELD_LENGTH(alg)`
    :code:`((alg)==PSA_ALG_MD2 ? 1 : (alg)==PSA_ALG_MD4 || (alg)==PSA_ALG_MD5 || (alg)==PSA_ALG_RIPEMD160 || (alg)==PSA_ALG_SHA_1 || (alg)==PSA_ALG_SHA_224 || (alg)==PSA_ALG_SHA_256 ? 8 : (alg)==PSA_ALG_SHA_512 || (alg)==PSA_ALG_SHA_384 || (alg)==PSA_ALG_SHA_512_256 ? 16 : 0)`

    .. Could simplify if allowed to return 8 for every alg value that is not MD2 or SHA512/SHA384/SHA512-256

:code:`PSA_HASH_SUSPEND_OUTPUT_SIZE(alg)`
    :code:`(PSA_HASH_SUSPEND_ALGORITHM_FIELD_LENGTH + PSA_HASH_SUSPEND_INPUT_LENGTH_FIELD_LENGTH(alg) + PSA_HASH_SUSPEND_HASH_STATE_FIELD_LENGTH(alg) + PSA_HASH_BLOCK_LENGTH(alg) - 1)`
