/* Copyright 2015 The Chromium OS Authors. All rights reserved. * 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 #if defined(CR50_DEV) && (CR50_DEV) > 1 #define CRYPTO_TEST_SETUP #endif #include "internal.h" #include "crypto_api.h" #include #include "cryptoc/hmac.h" enum cipher_mode { CIPHER_MODE_ECB = 0, CIPHER_MODE_CTR = 1, CIPHER_MODE_CBC = 2, CIPHER_MODE_GCM = 3 }; 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. */ #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); 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 */ 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, 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 */ /* 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); 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. */ void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key, unsigned int len); 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 }; /* 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 */ 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 */ 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 */ 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. */ int DCRYPTO_p256_base_point_mul(p256_int *out_x, p256_int *out_y, const p256_int *n); 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); /* * 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). */ /* 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. */ 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. */ 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. */ 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. */ int DCRYPTO_x509_verify(const uint8_t *cert, size_t len, const struct RSA *ca_pub_key); 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 { }; int DCRYPTO_ladder_compute_frk2(size_t major_fw_version, uint8_t *frk2); int DCRYPTO_ladder_random(void *output); 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 /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */