static void ec_GFp_simple_mul_single(const EC_GROUP *group, EC_RAW_POINT *r, const EC_RAW_POINT *p, const EC_SCALAR *scalar) { // This is a generic implementation for uncommon curves that not do not // warrant a tuned one. It uses unsigned digits so that the doubling case in // |ec_GFp_simple_add| is always unreachable, erring on safety and simplicity. // Compute a table of the first 32 multiples of |p| (including infinity). EC_RAW_POINT precomp[32]; ec_GFp_simple_point_set_to_infinity(group, &precomp[0]); ec_GFp_simple_point_copy(&precomp[1], p); for (size_t j = 2; j < OPENSSL_ARRAY_SIZE(precomp); j++) { if (j & 1) { ec_GFp_simple_add(group, &precomp[j], &precomp[1], &precomp[j - 1]); } else { ec_GFp_simple_dbl(group, &precomp[j], &precomp[j / 2]); } } // Divide bits in |scalar| into windows. unsigned bits = BN_num_bits(&group->order); int r_is_at_infinity = 1; for (unsigned i = bits - 1; i < bits; i--) { if (!r_is_at_infinity) { ec_GFp_simple_dbl(group, r, r); } if (i % 5 == 0) { // Compute the next window value. const size_t width = group->order.width; uint8_t window = bn_is_bit_set_words(scalar->words, width, i + 4) << 4; window |= bn_is_bit_set_words(scalar->words, width, i + 3) << 3; window |= bn_is_bit_set_words(scalar->words, width, i + 2) << 2; window |= bn_is_bit_set_words(scalar->words, width, i + 1) << 1; window |= bn_is_bit_set_words(scalar->words, width, i); // Select the entry in constant-time. EC_RAW_POINT tmp; OPENSSL_memset(&tmp, 0, sizeof(EC_RAW_POINT)); for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(precomp); j++) { BN_ULONG mask = constant_time_eq_w(j, window); ec_felem_select(group, &tmp.X, mask, &precomp[j].X, &tmp.X); ec_felem_select(group, &tmp.Y, mask, &precomp[j].Y, &tmp.Y); ec_felem_select(group, &tmp.Z, mask, &precomp[j].Z, &tmp.Z); } if (r_is_at_infinity) { ec_GFp_simple_point_copy(r, &tmp); r_is_at_infinity = 0; } else { ec_GFp_simple_add(group, r, r, &tmp); } } } if (r_is_at_infinity) { ec_GFp_simple_point_set_to_infinity(group, r); } }
DEFINE_LOCAL_DATA(BIGNUM, g_small_factors) { out->d = (BN_ULONG *) kSmallFactorsLimbs; out->top = OPENSSL_ARRAY_SIZE(kSmallFactorsLimbs); out->dmax = out->top; out->neg = 0; out->flags = BN_FLG_STATIC_DATA; }
static const SSL_ECDH_METHOD *method_from_nid(int nid) { for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) { if (kMethods[i].nid == nid) { return &kMethods[i]; } } return NULL; }
static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) { for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) { if (kMethods[i].group_id == group_id) { return &kMethods[i]; } } return NULL; }
static const SSL_ECDH_METHOD *method_from_name(const char *name, size_t len) { for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) { if (len == strlen(kMethods[i].name) && !strncmp(kMethods[i].name, name, len)) { return &kMethods[i]; } } return NULL; }
int main(void) { uint8_t buf[82], prk[EVP_MAX_MD_SIZE]; size_t i, prk_len; CRYPTO_library_init(); for (i = 0; i < OPENSSL_ARRAY_SIZE(kTests); i++) { const hkdf_test_vector_t *test = &kTests[i]; if (!HKDF_extract(prk, &prk_len, test->md_func(), test->ikm, test->ikm_len, test->salt, test->salt_len)) { fprintf(stderr, "Call to HKDF_extract failed\n"); ERR_print_errors_fp(stderr); return 1; } if (prk_len != test->prk_len || memcmp(prk, test->prk, test->prk_len) != 0) { fprintf(stderr, "%zu: Resulting PRK does not match test vector\n", i); return 1; } if (!HKDF_expand(buf, test->out_len, test->md_func(), prk, prk_len, test->info, test->info_len)) { fprintf(stderr, "Call to HKDF_expand failed\n"); ERR_print_errors_fp(stderr); return 1; } if (memcmp(buf, test->out, test->out_len) != 0) { fprintf(stderr, "%zu: Resulting key material does not match test vector\n", i); return 1; } if (!HKDF(buf, test->out_len, test->md_func(), test->ikm, test->ikm_len, test->salt, test->salt_len, test->info, test->info_len)) { fprintf(stderr, "Call to HKDF failed\n"); ERR_print_errors_fp(stderr); return 1; } if (memcmp(buf, test->out, test->out_len) != 0) { fprintf(stderr, "%zu: Resulting key material does not match test vector\n", i); return 1; } } printf("PASS\n"); ERR_free_strings(); return 0; }
static int parse_key_type(CBS *cbs, int *out_type) { CBS oid; if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) { return 0; } for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) { const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i]; if (CBS_len(&oid) == method->oid_len && OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) { *out_type = method->pkey_id; return 1; } } return 0; }
int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) { SSL *const ssl = hs->ssl; CBS cbs, context, certificate_list; CBS_init(&cbs, ssl->init_msg, ssl->init_num); if (!CBS_get_u8_length_prefixed(&cbs, &context) || CBS_len(&context) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); return 0; } const int retain_sha256 = ssl->server && ssl->retain_only_sha256_of_client_certs; int ret = 0; EVP_PKEY *pkey = NULL; STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null(); if (certs == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } while (CBS_len(&certificate_list) > 0) { CBS certificate, extensions; if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) || !CBS_get_u16_length_prefixed(&certificate_list, &extensions) || CBS_len(&certificate) == 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 0) { pkey = ssl_cert_parse_pubkey(&certificate); if (pkey == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); goto err; } /* TLS 1.3 always uses certificate keys for signing thus the correct * keyUsage is enforced. */ if (!ssl_cert_check_digital_signature_key_usage(&certificate)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); goto err; } if (retain_sha256) { /* Retain the hash of the leaf certificate if requested. */ SHA256(CBS_data(&certificate), CBS_len(&certificate), ssl->s3->new_session->peer_sha256); } } CRYPTO_BUFFER *buf = CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool); if (buf == NULL || !sk_CRYPTO_BUFFER_push(certs, buf)) { CRYPTO_BUFFER_free(buf); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); goto err; } /* Parse out the extensions. */ int have_status_request = 0, have_sct = 0; CBS status_request, sct; const SSL_EXTENSION_TYPE ext_types[] = { {TLSEXT_TYPE_status_request, &have_status_request, &status_request}, {TLSEXT_TYPE_certificate_timestamp, &have_sct, &sct}, }; uint8_t alert; if (!ssl_parse_extensions(&extensions, &alert, ext_types, OPENSSL_ARRAY_SIZE(ext_types), 0 /* reject unknown */)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); goto err; } /* All Certificate extensions are parsed, but only the leaf extensions are * stored. */ if (have_status_request) { if (ssl->server || !ssl->ocsp_stapling_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } uint8_t status_type; CBS ocsp_response; if (!CBS_get_u8(&status_request, &status_type) || status_type != TLSEXT_STATUSTYPE_ocsp || !CBS_get_u24_length_prefixed(&status_request, &ocsp_response) || CBS_len(&ocsp_response) == 0 || CBS_len(&status_request) != 0) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&ocsp_response, &ssl->s3->new_session->ocsp_response, &ssl->s3->new_session->ocsp_response_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } if (have_sct) { if (ssl->server || !ssl->signed_cert_timestamps_enabled) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); goto err; } if (!ssl_is_sct_list_valid(&sct)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(certs) == 1 && !CBS_stow(&sct, &ssl->s3->new_session->tlsext_signed_cert_timestamp_list, &ssl->s3->new_session ->tlsext_signed_cert_timestamp_list_length)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); goto err; } } } if (CBS_len(&cbs) != 0) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } EVP_PKEY_free(hs->peer_pubkey); hs->peer_pubkey = pkey; pkey = NULL; sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free); ssl->s3->new_session->certs = certs; certs = NULL; if (!ssl_session_x509_cache_objects(ssl->s3->new_session)) { OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); goto err; } if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) { if (!allow_anonymous) { OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED); goto err; } /* OpenSSL returns X509_V_OK when no certificates are requested. This is * classed by them as a bug, but it's assumed by at least NGINX. */ ssl->s3->new_session->verify_result = X509_V_OK; /* No certificate, so nothing more to do. */ ret = 1; goto err; } ssl->s3->new_session->peer_sha256_valid = retain_sha256; if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result, ssl->s3->new_session->x509_chain)) { goto err; } ret = 1; err: sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free); EVP_PKEY_free(pkey); return ret; }
// True const BN_ULONG kBoringSSLRSASqrtTwo[] = { TOBN(0xdea06241, 0xf7aa81c2), TOBN(0xf6a1be3f, 0xca221307), TOBN(0x332a5e9f, 0x7bda1ebf), TOBN(0x0104dc01, 0xfe32352f), TOBN(0xb8cf341b, 0x6f8236c7), TOBN(0x4264dabc, 0xd528b651), TOBN(0xf4d3a02c, 0xebc93e0c), TOBN(0x81394ab6, 0xd8fd0efd), TOBN(0xeaa4a089, 0x9040ca4a), TOBN(0xf52f120f, 0x836e582e), TOBN(0xcb2a6343, 0x31f3c84d), TOBN(0xc6d5a8a3, 0x8bb7e9dc), TOBN(0x460abc72, 0x2f7c4e33), TOBN(0xcab1bc91, 0x1688458a), TOBN(0x53059c60, 0x11bc337b), TOBN(0xd2202e87, 0x42af1f4e), TOBN(0x78048736, 0x3dfa2768), TOBN(0x0f74a85e, 0x439c7b4a), TOBN(0xa8b1fe6f, 0xdc83db39), TOBN(0x4afc8304, 0x3ab8a2c3), TOBN(0xed17ac85, 0x83339915), TOBN(0x1d6f60ba, 0x893ba84c), TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484), }; const size_t kBoringSSLRSASqrtTwoLen = OPENSSL_ARRAY_SIZE(kBoringSSLRSASqrtTwo); // generate_prime sets |out| to a prime with length |bits| such that |out|-1 is // relatively prime to |e|. If |p| is non-NULL, |out| will also not be close to // |p|. |sqrt2| must be ⌊2^(bits-1)×√2⌋ (or a slightly overestimate for large // sizes), and |pow2_bits_100| must be 2^(bits-100). static int generate_prime(BIGNUM *out, int bits, const BIGNUM *e, const BIGNUM *p, const BIGNUM *sqrt2, const BIGNUM *pow2_bits_100, BN_CTX *ctx, BN_GENCB *cb) { if (bits < 128 || (bits % BN_BITS2) != 0) { OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); return 0; } assert(BN_is_pow2(pow2_bits_100)); assert(BN_is_bit_set(pow2_bits_100, bits - 100));
static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group, EC_RAW_POINT *r, const EC_SCALAR *g_scalar, const EC_RAW_POINT *p, const EC_SCALAR *p_scalar) { #define P256_WSIZE_PUBLIC 4 // Precompute multiples of |p|. p_pre_comp[i] is (2*i+1) * |p|. fe p_pre_comp[1 << (P256_WSIZE_PUBLIC-1)][3]; fe_from_generic(p_pre_comp[0][0], &p->X); fe_from_generic(p_pre_comp[0][1], &p->Y); fe_from_generic(p_pre_comp[0][2], &p->Z); fe p2[3]; point_double(p2[0], p2[1], p2[2], p_pre_comp[0][0], p_pre_comp[0][1], p_pre_comp[0][2]); for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) { point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2], p_pre_comp[i - 1][0], p_pre_comp[i - 1][1], p_pre_comp[i - 1][2], 0 /* not mixed */, p2[0], p2[1], p2[2]); } // Set up the coefficients for |p_scalar|. int8_t p_wNAF[257]; ec_compute_wNAF(group, p_wNAF, p_scalar, 256, P256_WSIZE_PUBLIC); // Set |ret| to the point at infinity. int skip = 1; // Save some point operations. fe ret[3] = {{0},{0},{0}}; for (int i = 256; i >= 0; i--) { if (!skip) { point_double(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2]); } // For the |g_scalar|, we use the precomputed table without the // constant-time lookup. if (i <= 31) { // First, look 32 bits upwards. uint64_t bits = get_bit(g_scalar->bytes, i + 224) << 3; bits |= get_bit(g_scalar->bytes, i + 160) << 2; bits |= get_bit(g_scalar->bytes, i + 96) << 1; bits |= get_bit(g_scalar->bytes, i + 32); point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], 1 /* mixed */, g_pre_comp[1][bits][0], g_pre_comp[1][bits][1], g_pre_comp[1][bits][2]); skip = 0; // Second, look at the current position. bits = get_bit(g_scalar->bytes, i + 192) << 3; bits |= get_bit(g_scalar->bytes, i + 128) << 2; bits |= get_bit(g_scalar->bytes, i + 64) << 1; bits |= get_bit(g_scalar->bytes, i); point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], 1 /* mixed */, g_pre_comp[0][bits][0], g_pre_comp[0][bits][1], g_pre_comp[0][bits][2]); } int digit = p_wNAF[i]; if (digit != 0) { assert(digit & 1); int idx = digit < 0 ? (-digit) >> 1 : digit >> 1; fe *y = &p_pre_comp[idx][1], tmp; if (digit < 0) { fe_opp(tmp, p_pre_comp[idx][1]); y = &tmp; } if (!skip) { point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], 0 /* not mixed */, p_pre_comp[idx][0], *y, p_pre_comp[idx][2]); } else { fe_copy(ret[0], p_pre_comp[idx][0]); fe_copy(ret[1], *y); fe_copy(ret[2], p_pre_comp[idx][2]); skip = 0; } } }