/* * Copyright (c) 2016 Thomas Pornin * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* * Trimmed BearSSL internal header for LITLS. * Contains only the types and declarations needed for: * - AES-CTR (constant-time bitsliced) * - GHASH (ctmul32) * - i15 big integer library * - ECDSA P-256 (sign + verify) * - RSA PKCS#1 v1.5 verify * - SHA-256 vtable, HMAC, HMAC-DRBG (for RFC 6979) */ #ifndef INNER_H__ #define INNER_H__ #include #include #include #include /* ==================================================================== */ /* Architecture detection */ #ifndef BR_64 #if ((ULONG_MAX >> 31) >> 31) == 3 #define BR_64 1 #elif defined(__ia64) || defined(__itanium__) || defined(_M_IA64) #define BR_64 1 #elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(__64BIT__) || defined(_LP64) || \ defined(__LP64__) #define BR_64 1 #elif defined(__sparc64__) #define BR_64 1 #elif defined(__x86_64__) || defined(_M_X64) #define BR_64 1 #elif defined(__aarch64__) || defined(_M_ARM64) #define BR_64 1 #elif defined(__mips64) #define BR_64 1 #endif #endif /* Unaligned access detection */ #if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED #if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64 #define BR_LE_UNALIGNED 1 #endif #endif /* ==================================================================== */ /* Size constants */ #define BR_MAX_RSA_SIZE 4096 #define BR_MAX_RSA_FACTOR ((BR_MAX_RSA_SIZE + 64) >> 1) #define BR_MAX_EC_SIZE 528 /* EC curve IDs */ #define BR_EC_secp256r1 23 #define BR_EC_secp384r1 24 #define BR_EC_secp521r1 25 /* ==================================================================== */ /* Encoding/decoding functions */ typedef union { uint16_t u; unsigned char b[sizeof(uint16_t)]; } br_union_u16; typedef union { uint32_t u; unsigned char b[sizeof(uint32_t)]; } br_union_u32; typedef union { uint64_t u; unsigned char b[sizeof(uint64_t)]; } br_union_u64; static inline void br_enc16le(void *dst, unsigned x) { #if BR_LE_UNALIGNED ((br_union_u16 *)dst)->u = x; #else unsigned char *buf = dst; buf[0] = (unsigned char)x; buf[1] = (unsigned char)(x >> 8); #endif } static inline void br_enc16be(void *dst, unsigned x) { unsigned char *buf = dst; buf[0] = (unsigned char)(x >> 8); buf[1] = (unsigned char)x; } static inline unsigned br_dec16le(const void *src) { #if BR_LE_UNALIGNED return ((const br_union_u16 *)src)->u; #else const unsigned char *buf = src; return (unsigned)buf[0] | ((unsigned)buf[1] << 8); #endif } static inline unsigned br_dec16be(const void *src) { const unsigned char *buf = src; return ((unsigned)buf[0] << 8) | (unsigned)buf[1]; } static inline void br_enc32le(void *dst, uint32_t x) { #if BR_LE_UNALIGNED ((br_union_u32 *)dst)->u = x; #else unsigned char *buf = dst; buf[0] = (unsigned char)x; buf[1] = (unsigned char)(x >> 8); buf[2] = (unsigned char)(x >> 16); buf[3] = (unsigned char)(x >> 24); #endif } static inline void br_enc32be(void *dst, uint32_t x) { unsigned char *buf = dst; buf[0] = (unsigned char)(x >> 24); buf[1] = (unsigned char)(x >> 16); buf[2] = (unsigned char)(x >> 8); buf[3] = (unsigned char)x; } static inline uint32_t br_dec32le(const void *src) { #if BR_LE_UNALIGNED return ((const br_union_u32 *)src)->u; #else const unsigned char *buf = src; return (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 24); #endif } static inline uint32_t br_dec32be(const void *src) { const unsigned char *buf = src; return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | (uint32_t)buf[3]; } static inline void br_enc64le(void *dst, uint64_t x) { unsigned char *buf = dst; br_enc32le(buf, (uint32_t)x); br_enc32le(buf + 4, (uint32_t)(x >> 32)); } static inline void br_enc64be(void *dst, uint64_t x) { unsigned char *buf = dst; br_enc32be(buf, (uint32_t)(x >> 32)); br_enc32be(buf + 4, (uint32_t)x); } static inline uint64_t br_dec64le(const void *src) { const unsigned char *buf = src; return (uint64_t)br_dec32le(buf) | ((uint64_t)br_dec32le(buf + 4) << 32); } static inline uint64_t br_dec64be(const void *src) { const unsigned char *buf = src; return ((uint64_t)br_dec32be(buf) << 32) | (uint64_t)br_dec32be(buf + 4); } static inline uint32_t br_swap32(uint32_t x) { x = ((x & (uint32_t)0x00FF00FF) << 8) | ((x >> 8) & (uint32_t)0x00FF00FF); return (x << 16) | (x >> 16); } /* ==================================================================== */ /* Block cipher types (AES-CTR) */ typedef struct br_block_ctr_class_ br_block_ctr_class; struct br_block_ctr_class_ { size_t context_size; unsigned block_size; unsigned log_block_size; void (*init)(const br_block_ctr_class **ctx, const void *key, size_t key_len); uint32_t (*run)(const br_block_ctr_class *const *ctx, const void *iv, uint32_t cc, void *data, size_t len); }; typedef struct { const br_block_ctr_class *vtable; uint32_t skey[60]; unsigned num_rounds; } br_aes_ct_ctr_keys; extern const br_block_ctr_class br_aes_ct_ctr_vtable; /* AES-CTR procedural API */ void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx, const void *key, size_t len); uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len); /* AES-CT internal functions */ void br_aes_ct_ortho(uint32_t *q); void br_aes_ct_bitslice_Sbox(uint32_t *q); void br_aes_ct_bitslice_encrypt(unsigned num_rounds, const uint32_t *skey, uint32_t *q); unsigned br_aes_ct_keysched(uint32_t *comp_skey, const void *key, size_t key_len); void br_aes_ct_skey_expand(uint32_t *skey, unsigned num_rounds, const uint32_t *comp_skey); /* ==================================================================== */ /* GHASH type */ typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); /* ==================================================================== */ /* Hash vtable (needed by HMAC/HMAC-DRBG for ECDSA RFC 6979) */ typedef struct br_hash_class_ br_hash_class; struct br_hash_class_ { size_t context_size; uint32_t desc; void (*init)(const br_hash_class **ctx); void (*update)(const br_hash_class **ctx, const void *data, size_t len); void (*out)(const br_hash_class **ctx, void *dst); void (*state)(const br_hash_class **ctx, void *stb); void (*set_state)(const br_hash_class **ctx, const void *stb, uint64_t count); }; #define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) #define BR_HASHDESC_ID_OFF 0 #define BR_HASHDESC_ID_MASK 0xFF #define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) #define BR_HASHDESC_OUT_OFF 8 #define BR_HASHDESC_OUT_MASK 0x7F #define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) #define BR_HASHDESC_STATE_OFF 15 #define BR_HASHDESC_STATE_MASK 0xFF #define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) #define BR_HASHDESC_LBLEN_OFF 23 #define BR_HASHDESC_LBLEN_MASK 0x0F #define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) #define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) #define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) /* SHA-224 context (also used as SHA-256 context) */ typedef struct { const br_hash_class *vtable; unsigned char buf[64]; uint64_t count; uint32_t val[8]; } br_sha224_context; typedef br_sha224_context br_sha256_context; extern const br_hash_class br_sha224_vtable; extern const br_hash_class br_sha256_vtable; /* Hash IDs */ #define br_sha224_ID 3 #define br_sha256_ID 4 /* SHA-224/256 function declarations */ void br_sha224_init(br_sha224_context *cc); void br_sha224_update(br_sha224_context *cc, const void *data, size_t len); void br_sha224_out(const br_sha224_context *cc, void *dst); void br_sha256_init(br_sha256_context *cc); void br_sha256_out(const br_sha256_context *cc, void *dst); /* SHA-256 is SHA-224 with different IV and output size */ #define br_sha256_update br_sha224_update #define br_sha256_state br_sha224_state #define br_sha256_set_state br_sha224_set_state /* Minimal hash compat context for HMAC */ typedef union { const br_hash_class *vtable; br_sha224_context sha224; br_sha256_context sha256; } br_hash_compat_context; /* SHA-256 round function and IVs (needed by sha2small.c) */ extern const uint32_t br_sha256_IV[]; extern const uint32_t br_sha224_IV[]; void br_sha2small_round(const unsigned char *buf, uint32_t *val); /* Range encoding/decoding (needed by sha2small.c) */ static inline void br_range_dec32be(uint32_t *v, size_t num, const void *src) { const unsigned char *buf = src; while (num-- > 0) { *v++ = br_dec32be(buf); buf += 4; } } static inline void br_range_enc32be(void *dst, const uint32_t *v, size_t num) { unsigned char *buf = dst; while (num-- > 0) { br_enc32be(buf, *v++); buf += 4; } } static inline size_t br_digest_size(const br_hash_class *digest_class) { return (size_t)(digest_class->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK; } /* ==================================================================== */ /* HMAC */ typedef struct { const br_hash_class *dig_vtable; unsigned char ksi[64], kso[64]; } br_hmac_key_context; typedef struct { br_hash_compat_context dig; unsigned char kso[64]; size_t out_len; } br_hmac_context; void br_hmac_key_init(br_hmac_key_context *kc, const br_hash_class *digest_vtable, const void *key, size_t key_len); void br_hmac_init(br_hmac_context *ctx, const br_hmac_key_context *kc, size_t out_len); static inline size_t br_hmac_size(br_hmac_context *ctx) { return ctx->out_len; } void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len); size_t br_hmac_out(const br_hmac_context *ctx, void *out); /* ==================================================================== */ /* HMAC-DRBG (RFC 6979 k-generation for ECDSA) */ typedef struct br_prng_class_ br_prng_class; struct br_prng_class_ { size_t context_size; void (*init)(const br_prng_class **ctx, const void *params, const void *seed, size_t seed_len); void (*generate)(const br_prng_class **ctx, void *out, size_t len); void (*update)(const br_prng_class **ctx, const void *seed, size_t seed_len); }; typedef struct { const br_prng_class *vtable; unsigned char K[64]; unsigned char V[64]; const br_hash_class *digest_class; } br_hmac_drbg_context; extern const br_prng_class br_hmac_drbg_vtable; void br_hmac_drbg_init(br_hmac_drbg_context *ctx, const br_hash_class *digest_class, const void *seed, size_t seed_len); void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len); void br_hmac_drbg_update(br_hmac_drbg_context *ctx, const void *seed, size_t seed_len); /* ==================================================================== */ /* Constant-time primitives */ static inline uint32_t NOT(uint32_t ctl) { return ctl ^ 1; } static inline uint32_t MUX(uint32_t ctl, uint32_t x, uint32_t y) { return y ^ (-ctl & (x ^ y)); } static inline uint32_t EQ(uint32_t x, uint32_t y) { uint32_t q = x ^ y; return NOT((q | -q) >> 31); } static inline uint32_t NEQ(uint32_t x, uint32_t y) { uint32_t q = x ^ y; return (q | -q) >> 31; } static inline uint32_t GT(uint32_t x, uint32_t y) { uint32_t z = y - x; return (z ^ ((x ^ y) & (x ^ z))) >> 31; } #define GE(x, y) NOT(GT(y, x)) #define LT(x, y) GT(y, x) #define LE(x, y) NOT(GT(x, y)) static inline int32_t CMP(uint32_t x, uint32_t y) { return (int32_t)GT(x, y) | -(int32_t)GT(y, x); } static inline uint32_t EQ0(int32_t x) { uint32_t q = (uint32_t)x; return ~(q | -q) >> 31; } static inline uint32_t GT0(int32_t x) { uint32_t q = (uint32_t)x; return (~q & -q) >> 31; } static inline uint32_t GE0(int32_t x) { return ~(uint32_t)x >> 31; } static inline uint32_t LT0(int32_t x) { return (uint32_t)x >> 31; } static inline uint32_t LE0(int32_t x) { uint32_t q = (uint32_t)x; return (q | ~-q) >> 31; } void br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len); #define CCOPY br_ccopy static inline uint32_t BIT_LENGTH(uint32_t x) { uint32_t k, c; k = NEQ(x, 0); c = GT(x, 0xFFFF); x = MUX(c, x >> 16, x); k += c << 4; c = GT(x, 0x00FF); x = MUX(c, x >> 8, x); k += c << 3; c = GT(x, 0x000F); x = MUX(c, x >> 4, x); k += c << 2; c = GT(x, 0x0003); x = MUX(c, x >> 2, x); k += c << 1; k += GT(x, 0x0001); return k; } static inline uint32_t MIN(uint32_t x, uint32_t y) { return MUX(GT(x, y), y, x); } static inline uint32_t MAX(uint32_t x, uint32_t y) { return MUX(GT(x, y), x, y); } #define MUL(x, y) ((uint64_t)(x) * (uint64_t)(y)) #define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y)) #define MUL31_lo(x, y) (((uint32_t)(x) * (uint32_t)(y)) & (uint32_t)0x7FFFFFFF) #define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y)) #define ARSH(x, n) ((*(int32_t *)&(x)) >> (n)) uint32_t br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r); static inline uint32_t br_rem(uint32_t hi, uint32_t lo, uint32_t d) { uint32_t r; br_divrem(hi, lo, d, &r); return r; } static inline uint32_t br_div(uint32_t hi, uint32_t lo, uint32_t d) { uint32_t r; return br_divrem(hi, lo, d, &r); } /* ==================================================================== */ /* i15 big integer library */ static inline void br_i15_zero(uint16_t *x, uint16_t bit_len) { *x++ = bit_len; memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x); } uint32_t br_i15_iszero(const uint16_t *x); uint16_t br_i15_ninv15(uint16_t x); uint32_t br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl); uint32_t br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl); void br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m); void br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y, const uint16_t *m, uint16_t m0i); void br_i15_to_monty(uint16_t *x, const uint16_t *m); void br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i); void br_i15_modpow(uint16_t *x, const unsigned char *e, size_t elen, const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2); uint32_t br_i15_modpow_opt(uint16_t *x, const unsigned char *e, size_t elen, const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen); void br_i15_encode(void *dst, size_t len, const uint16_t *x); uint32_t br_i15_decode_mod(uint16_t *x, const void *src, size_t len, const uint16_t *m); void br_i15_rshift(uint16_t *x, int count); uint32_t br_i15_bit_length(uint16_t *x, size_t xlen); void br_i15_decode(uint16_t *x, const void *src, size_t len); void br_i15_decode_reduce(uint16_t *x, const void *src, size_t len, const uint16_t *m); void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m); void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b); uint32_t br_i15_moddiv(uint16_t *x, const uint16_t *y, const uint16_t *m, uint16_t m0i, uint16_t *t); /* ==================================================================== */ /* Elliptic curves */ typedef struct { uint32_t supported_curves; const unsigned char *(*generator)(int curve, size_t *len); const unsigned char *(*order)(int curve, size_t *len); size_t (*xoff)(int curve, size_t *len); uint32_t (*mul)(unsigned char *G, size_t Glen, const unsigned char *x, size_t xlen, int curve); size_t (*mulgen)(unsigned char *R, const unsigned char *x, size_t xlen, int curve); uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len, const unsigned char *x, size_t xlen, const unsigned char *y, size_t ylen, int curve); } br_ec_impl; typedef struct { int curve; unsigned char *q; size_t qlen; } br_ec_public_key; typedef struct { int curve; unsigned char *x; size_t xlen; } br_ec_private_key; typedef struct { int curve; const unsigned char *order; size_t order_len; const unsigned char *generator; size_t generator_len; } br_ec_curve_def; extern const br_ec_curve_def br_secp256r1; extern const br_ec_curve_def br_secp384r1; extern const br_ec_curve_def br_secp521r1; extern const br_ec_impl br_ec_p256_m15; extern const br_ec_impl br_ec_prime_i15; size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk, void *kbuf, const br_ec_private_key *sk); size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl, const br_hash_class *hf, const void *hash_value, const br_ec_private_key *sk, void *sig); uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl, const void *hash, size_t hash_len, const br_ec_public_key *pk, const void *sig, size_t sig_len); void br_ecdsa_i15_bits2int(uint16_t *x, const void *src, size_t len, uint32_t ebitlen); /* ==================================================================== */ /* RSA */ typedef struct { unsigned char *n; size_t nlen; unsigned char *e; size_t elen; } br_rsa_public_key; uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen, const br_rsa_public_key *pk); uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen, const unsigned char *hash_oid, size_t hash_len, const br_rsa_public_key *pk, unsigned char *hash_out); uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len, const unsigned char *hash_oid, size_t hash_len, unsigned char *hash_out); #endif /* INNER_H__ */