| /* Copyright 2015 The ChromiumOS Authors |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| /* |
| * Crypto wrapper library for the g chip. |
| */ |
| #ifndef __EC_CHIP_G_DCRYPTO_DCRYPTO_H |
| #define __EC_CHIP_G_DCRYPTO_DCRYPTO_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #if defined(TEST_FUZZ) || !defined(TEST_BUILD) |
| |
| #include "internal.h" |
| |
| #include "crypto_api.h" |
| |
| #include <stddef.h> |
| |
| #include "cryptoc/hmac.h" |
| |
| enum cipher_mode { |
| CIPHER_MODE_ECB = 0, /* NIST SP 800-38A */ |
| CIPHER_MODE_CTR = 1, /* NIST SP 800-38A */ |
| CIPHER_MODE_CBC = 2, /* NIST SP 800-38A */ |
| CIPHER_MODE_GCM = 3 /* NIST SP 800-38D */ |
| }; |
| |
| enum encrypt_mode { |
| DECRYPT_MODE = 0, |
| ENCRYPT_MODE = 1 |
| }; |
| |
| enum hashing_mode { |
| HASH_SHA1 = 0, |
| HASH_SHA256 = 1, |
| HASH_SHA384 = 2, /* Only supported for PKCS#1 signing */ |
| HASH_SHA512 = 3, /* Only supported for PKCS#1 signing */ |
| HASH_NULL = 4 /* Only supported for PKCS#1 signing */ |
| }; |
| |
| /* |
| * AES implementation, based on a hardware AES block. |
| * FIPS Publication 197, The Advanced Encryption Standard (AES) |
| */ |
| #define AES256_BLOCK_CIPHER_KEY_SIZE 32 |
| |
| int DCRYPTO_aes_init(const uint8_t *key, uint32_t key_len, const uint8_t *iv, |
| enum cipher_mode c_mode, enum encrypt_mode e_mode); |
| int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out); |
| |
| void DCRYPTO_aes_write_iv(const uint8_t *iv); |
| void DCRYPTO_aes_read_iv(uint8_t *iv); |
| |
| /* AES-CTR-128/192/256 |
| * NIST Special Publication 800-38A |
| */ |
| int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits, |
| const uint8_t *iv, const uint8_t *in, size_t in_len); |
| |
| /* AES-GCM-128/192/256 |
| * NIST Special Publication 800-38D, IV is provided externally |
| * Caller should use IV length according to section 8.2 of SP 800-38D |
| * And choose appropriate IV construction method, constrain number |
| * of invocations according to section 8.3 of SP 800-38D |
| */ |
| struct GCM_CTX { |
| union { |
| uint32_t d[4]; |
| uint8_t c[16]; |
| } block, Ej0; |
| |
| uint64_t aad_len; |
| uint64_t count; |
| size_t remainder; |
| }; |
| |
| /* Initialize the GCM context structure. */ |
| void DCRYPTO_gcm_init(struct GCM_CTX *ctx, uint32_t key_bits, |
| const uint8_t *key, const uint8_t *iv, size_t iv_len); |
| /* Additional authentication data to include in the tag calculation. */ |
| void DCRYPTO_gcm_aad(struct GCM_CTX *ctx, const uint8_t *aad_data, size_t len); |
| /* Encrypt & decrypt return the number of bytes written to out |
| * (always an integral multiple of 16), or -1 on error. These functions |
| * may be called repeatedly with incremental data. |
| * |
| * NOTE: if in_len is not a integral multiple of 16, then out_len must |
| * be atleast in_len - (in_len % 16) + 16 bytes. |
| */ |
| int DCRYPTO_gcm_encrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len, |
| const uint8_t *in, size_t in_len); |
| int DCRYPTO_gcm_decrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len, |
| const uint8_t *in, size_t in_len); |
| /* Encrypt & decrypt a partial final block, if any. These functions |
| * return the number of bytes written to out (<= 15), or -1 on error. |
| */ |
| int DCRYPTO_gcm_encrypt_final(struct GCM_CTX *ctx, |
| uint8_t *out, size_t out_len); |
| int DCRYPTO_gcm_decrypt_final(struct GCM_CTX *ctx, |
| uint8_t *out, size_t out_len); |
| /* Compute the tag over AAD + encrypt or decrypt data, and return the |
| * number of bytes written to tag. Returns -1 on error. |
| */ |
| int DCRYPTO_gcm_tag(struct GCM_CTX *ctx, uint8_t *tag, size_t tag_len); |
| /* Cleanup secrets. */ |
| void DCRYPTO_gcm_finish(struct GCM_CTX *ctx); |
| |
| /* AES-CMAC-128 |
| * NIST Special Publication 800-38B, RFC 4493 |
| * K: 128-bit key, M: message, len: number of bytes in M |
| * Writes 128-bit tag to T; returns 0 if an error is encountered and 1 |
| * otherwise. |
| */ |
| int DCRYPTO_aes_cmac(const uint8_t *K, const uint8_t *M, const uint32_t len, |
| uint32_t T[4]); |
| /* key: 128-bit key, M: message, len: number of bytes in M, |
| * T: tag to be verified |
| * Returns 1 if the tag is correct and 0 otherwise. |
| */ |
| int DCRYPTO_aes_cmac_verify(const uint8_t *key, const uint8_t *M, const int len, |
| const uint32_t T[4]); |
| |
| /* |
| * SHA implementation. This abstraction is backed by either a |
| * software or hardware implementation. |
| * |
| * There could be only a single hardware SHA context in progress. The init |
| * functions will try using the HW context, if available, unless 'sw_required' |
| * is TRUE, in which case there will be no attempt to use the hardware for |
| * this particular hashing session. |
| */ |
| void DCRYPTO_SHA1_init(SHA_CTX *ctx, uint32_t sw_required); |
| /* SHA256/384/512 FIPS 180-4 |
| */ |
| void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required); |
| void DCRYPTO_SHA384_init(LITE_SHA384_CTX *ctx); |
| void DCRYPTO_SHA512_init(LITE_SHA512_CTX *ctx); |
| const uint8_t *DCRYPTO_SHA1_hash(const void *data, uint32_t n, |
| uint8_t *digest); |
| const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n, |
| uint8_t *digest); |
| const uint8_t *DCRYPTO_SHA384_hash(const void *data, uint32_t n, |
| uint8_t *digest); |
| const uint8_t *DCRYPTO_SHA512_hash(const void *data, uint32_t n, |
| uint8_t *digest); |
| /* |
| * HMAC. FIPS 198-1 |
| */ |
| void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key, |
| unsigned int len); |
| /* DCRYPTO HMAC-SHA256 final */ |
| const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx); |
| |
| /* |
| * BIGNUM utility methods. |
| */ |
| void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len); |
| |
| /* |
| * RSA. |
| */ |
| |
| /* Largest supported key size for signing / encryption: 2048-bits. |
| * Verification is a special case and supports 4096-bits (signing / |
| * decryption could also support 4k-RSA, but is disabled since support |
| * is not required, and enabling support would result in increased |
| * stack usage for all key sizes.) |
| */ |
| #define RSA_BYTES_2K 256 |
| #define RSA_BYTES_4K 512 |
| #define RSA_WORDS_2K (RSA_BYTES_2K / sizeof(uint32_t)) |
| #define RSA_WORDS_4K (RSA_BYTES_4K / sizeof(uint32_t)) |
| #ifndef RSA_MAX_BYTES |
| #define RSA_MAX_BYTES RSA_BYTES_2K |
| #endif |
| #define RSA_MAX_WORDS (RSA_MAX_BYTES / sizeof(uint32_t)) |
| #define RSA_F4 65537 |
| |
| struct RSA { |
| uint32_t e; |
| struct LITE_BIGNUM N; |
| struct LITE_BIGNUM d; |
| }; |
| |
| enum padding_mode { |
| PADDING_MODE_PKCS1 = 0, |
| PADDING_MODE_OAEP = 1, |
| PADDING_MODE_PSS = 2, |
| /* USE OF NULL PADDING IS NOT RECOMMENDED. |
| * SUPPORT EXISTS AS A REQUIREMENT FOR TPM2 OPERATION. */ |
| PADDING_MODE_NULL = 3 |
| }; |
| |
| /* RSA support, FIPS PUB 186-4 * |
| * Calculate r = m ^ e mod N |
| */ |
| int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, uint32_t *out_len, |
| const uint8_t *in, uint32_t in_len, |
| enum padding_mode padding, enum hashing_mode hashing, |
| const char *label); |
| |
| /* Calculate r = m ^ d mod N |
| * return 0 if error |
| */ |
| int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, uint32_t *out_len, |
| const uint8_t *in, const uint32_t in_len, |
| enum padding_mode padding, enum hashing_mode hashing, |
| const char *label); |
| |
| /* Calculate r = m ^ d mod N |
| * return 0 if error |
| */ |
| int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, uint32_t *out_len, |
| const uint8_t *in, const uint32_t in_len, |
| enum padding_mode padding, enum hashing_mode hashing); |
| |
| /* Calculate r = m ^ e mod N |
| * return 0 if error |
| */ |
| int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest, |
| uint32_t digest_len, const uint8_t *sig, |
| const uint32_t sig_len, enum padding_mode padding, |
| enum hashing_mode hashing); |
| |
| /* Calculate n = p * q, d = e ^ -1 mod phi. */ |
| int DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, struct LITE_BIGNUM *d, |
| struct LITE_BIGNUM *p, struct LITE_BIGNUM *q, |
| uint32_t e); |
| |
| /* |
| * EC. |
| */ |
| |
| /* DCRYPTO_p256_base_point_mul sets {out_x,out_y} = nG, where n is < the |
| * order of the group. |
| */ |
| int DCRYPTO_p256_base_point_mul(p256_int *out_x, p256_int *out_y, |
| const p256_int *n); |
| |
| /* DCRYPTO_p256_point_mul sets {out_x,out_y} = n*{in_x,in_y}, where n is < |
| * the order of the group. |
| */ |
| int DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y, |
| const p256_int *n, const p256_int *in_x, |
| const p256_int *in_y); |
| /* |
| * Key selection based on FIPS-186-4, section B.4.2 (Key Pair |
| * Generation by Testing Candidates). |
| * Produce uniform private key from seed. |
| * If x or y is NULL, the public key part is not computed. |
| * Returns !0 on success. |
| */ |
| int DCRYPTO_p256_key_from_bytes(p256_int *x, p256_int *y, p256_int *d, |
| const uint8_t bytes[P256_NBYTES]); |
| |
| |
| /* P256 based integration encryption (DH+AES128+SHA256). |
| * Not FIPS 140-2 compliant, not used other than for tests |
| * Authenticated data may be provided, where the first auth_data_len |
| * bytes of in will be authenticated but not encrypted. * |
| * Supports in-place encryption / decryption. * |
| * The output format is: |
| * 0x04 || PUBKEY || AUTH_DATA || AES128_CTR(PLAINTEXT) || |
| * HMAC_SHA256(AUTH_DATA || CIPHERTEXT) |
| */ |
| size_t DCRYPTO_ecies_encrypt( |
| void *out, size_t out_len, const void *in, size_t in_len, |
| size_t auth_data_len, const uint8_t *iv, |
| const p256_int *pub_x, const p256_int *pub_y, |
| const uint8_t *salt, size_t salt_len, |
| const uint8_t *info, size_t info_len); |
| size_t DCRYPTO_ecies_decrypt( |
| void *out, size_t out_len, const void *in, size_t in_len, |
| size_t auth_data_len, const uint8_t *iv, |
| const p256_int *d, |
| const uint8_t *salt, size_t salt_len, |
| const uint8_t *info, size_t info_len); |
| |
| /* |
| * HKDF as per RFC 5869. Mentioned as conforming NIST SP 800-56C Rev.1 |
| * [RFC 5869] specifies a version of the above extraction-then-expansion |
| * key-derivation procedure using HMAC for both the extraction and expansion |
| * steps. |
| */ |
| int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len, |
| const uint8_t *salt, size_t salt_len, |
| const uint8_t *IKM, size_t IKM_len, |
| const uint8_t *info, size_t info_len); |
| |
| /* |
| * BN. |
| */ |
| |
| /* Apply Miller-Rabin test for prime candidate p. |
| * Returns 1 if test passed, 0 otherwise |
| */ |
| int DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p); |
| void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len); |
| void DCRYPTO_bn_mul(struct LITE_BIGNUM *c, const struct LITE_BIGNUM *a, |
| const struct LITE_BIGNUM *b); |
| int DCRYPTO_bn_div(struct LITE_BIGNUM *quotient, struct LITE_BIGNUM *remainder, |
| const struct LITE_BIGNUM *input, |
| const struct LITE_BIGNUM *divisor); |
| |
| /* |
| * ASN.1 DER |
| */ |
| size_t DCRYPTO_asn1_sigp(uint8_t *buf, const p256_int *r, const p256_int *s); |
| size_t DCRYPTO_asn1_pubp(uint8_t *buf, const p256_int *x, const p256_int *y); |
| |
| /* |
| * X509. |
| */ |
| /* DCRYPTO_x509_verify verifies that the provided X509 certificate was issued |
| * by the specified certifcate authority. |
| * |
| * cert is a pointer to a DER encoded X509 certificate, as specified |
| * in https://tools.ietf.org/html/rfc5280#section-4.1. In ASN.1 |
| * notation, the certificate has the following structure: |
| * |
| * Certificate ::= SEQUENCE { |
| * tbsCertificate TBSCertificate, |
| * signatureAlgorithm AlgorithmIdentifier, |
| * signatureValue BIT STRING } |
| * |
| * TBSCertificate ::= SEQUENCE { } |
| * AlgorithmIdentifier ::= SEQUENCE { } |
| * |
| * where signatureValue = SIGN(HASH(tbsCertificate)), with SIGN and |
| * HASH specified by signatureAlgorithm. |
| * Accepts only certs with OID: sha256WithRSAEncryption: |
| * 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |
| */ |
| int DCRYPTO_x509_verify(const uint8_t *cert, size_t len, |
| const struct RSA *ca_pub_key); |
| |
| /* Generate U2F Certificate and sign it |
| * Use ECDSA with NIST P-256 curve, and SHA2-256 digest |
| * @param d: key handle, used for NIST SP 800-90A HMAC DRBG |
| * @param pk_x, pk_y: public key |
| * @param serial: serial number for certificate |
| * @param name: certificate issuer and subject |
| * @param cert: output buffer for certificate |
| * @param n: max size of cert |
| */ |
| int DCRYPTO_x509_gen_u2f_cert_name(const p256_int *d, const p256_int *pk_x, |
| const p256_int *pk_y, const p256_int *serial, |
| const char *name, uint8_t *cert, |
| const int n); |
| |
| /* Generate U2F Certificate with DCRYPTO_x509_gen_u2f_cert_name |
| * Providing certificate issuer as BOARD or U2F |
| * @param d: key handle, used for NIST SP 800-90A HMAC DRBG |
| * @param pk_x, pk_y: public key |
| * @param serial: serial number for certificate |
| * @param name: certificate issuer and subject |
| * @param cert: output buffer for certificate |
| * @param n: max size of cert |
| */ |
| int DCRYPTO_x509_gen_u2f_cert(const p256_int *d, const p256_int *pk_x, |
| const p256_int *pk_y, const p256_int *serial, |
| uint8_t *cert, const int n); |
| |
| /* |
| * Memory related functions. |
| */ |
| int DCRYPTO_equals(const void *a, const void *b, size_t len); |
| |
| /* |
| * Key-ladder and application key related functions. |
| */ |
| enum dcrypto_appid { |
| RESERVED = 0, |
| NVMEM = 1, |
| U2F_ATTEST = 2, |
| U2F_ORIGIN = 3, |
| U2F_WRAP = 4, |
| PERSO_AUTH = 5, |
| PINWEAVER = 6, |
| /* This enum value should not exceed 7. */ |
| }; |
| |
| struct APPKEY_CTX { |
| #ifdef TEST_FUZZ |
| uint8_t unused_for_cxx_compatibility; |
| #endif |
| }; |
| |
| int DCRYPTO_ladder_compute_frk2(size_t major_fw_version, uint8_t *frk2); |
| int DCRYPTO_ladder_random(void *output); |
| void DCRYPTO_ladder_revoke(void); |
| |
| int DCRYPTO_appkey_init(enum dcrypto_appid id, struct APPKEY_CTX *ctx); |
| void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx); |
| int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8], |
| uint32_t output[8]); |
| |
| /* Number of bytes in the salt object. */ |
| #define DCRYPTO_CIPHER_SALT_SIZE 16 |
| BUILD_ASSERT(DCRYPTO_CIPHER_SALT_SIZE == CIPHER_SALT_SIZE); |
| |
| /* |
| * Encrypt/decrypt a flat blob. |
| * |
| * Encrypt or decrypt the input buffer, and write the correspondingly |
| * ciphered output to out. The number of bytes produced is equal to |
| * the number of input bytes. Note that the input and output pointers |
| * MUST be word-aligned. |
| * |
| * This API is expected to be applied to a single contiguous region. |
| |
| * WARNING: A given salt/"in" pair MUST be unique, i.e. re-using a |
| * salt with a logically different input buffer is catastrophic. An |
| * example of a suitable salt is one that is derived from "in", e.g. a |
| * digest of the input data. |
| * |
| * @param appid the application-id of the calling context. |
| * @param salt pointer to a unique value to be associated with this blob, |
| * used for derivation of the proper IV, the size of the value |
| * is as defined by DCRYPTO_CIPHER_SALT_SIZE above. |
| * @param out Destination pointer where to write plaintext / ciphertext. |
| * @param in Source pointer where to read ciphertext / plaintext. |
| * @param len Number of bytes to read from in / write to out. |
| * @return non-zero on success, and zero otherwise. |
| */ |
| int DCRYPTO_app_cipher(enum dcrypto_appid appid, const void *salt, |
| void *out, const void *in, size_t len); |
| |
| #endif /* ^^^^^^^^^^^^^^^^^^^^^ !TEST_BUILD */ |
| /* |
| * Query whether Key Ladder is enabled. |
| * |
| * @return 1 if Key Ladder is enabled, and 0 otherwise. |
| */ |
| int DCRYPTO_ladder_is_enabled(void); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */ |