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 || OPENSSL_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 (OPENSSL_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 (OPENSSL_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; }
int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len, const uint8_t *sig, size_t sig_len, const EC_KEY *eckey) { ECDSA_SIG *s; int ret = 0; uint8_t *der = NULL; /* Decode the ECDSA signature. */ s = ECDSA_SIG_from_bytes(sig, sig_len); if (s == NULL) { goto err; } /* Defend against potential laxness in the DER parser. */ size_t der_len; if (!ECDSA_SIG_to_bytes(&der, &der_len, s) || der_len != sig_len || OPENSSL_memcmp(sig, der, sig_len) != 0) { /* This should never happen. crypto/bytestring is strictly DER. */ OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR); goto err; } ret = ECDSA_do_verify(digest, digest_len, s, eckey); err: OPENSSL_free(der); ECDSA_SIG_free(s); return ret; }
int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b) { int ret; /* Ensure canonical encoding is present and up to date */ if (!a->canon_enc || a->modified) { ret = i2d_X509_NAME((X509_NAME *)a, NULL); if (ret < 0) return -2; } if (!b->canon_enc || b->modified) { ret = i2d_X509_NAME((X509_NAME *)b, NULL); if (ret < 0) return -2; } ret = a->canon_enclen - b->canon_enclen; if (ret) return ret; return OPENSSL_memcmp(a->canon_enc, b->canon_enc, a->canon_enclen); }
int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session) { if (session == NULL) { return 0; } return session->sid_ctx_length == ssl->cert->sid_ctx_length && OPENSSL_memcmp(session->sid_ctx, ssl->cert->sid_ctx, ssl->cert->sid_ctx_length) == 0; }
/* * Compare two certificates: they must be identical for this to work. NB: * Although "cmp" operations are generally prototyped to take "const" * arguments (eg. for use in STACKs), the way X509 handling is - these * operations may involve ensuring the hashes are up-to-date and ensuring * certain cert information is cached. So this is the point where the * "depth-first" constification tree has to halt with an evil cast. */ int X509_cmp(const X509 *a, const X509 *b) { int rv; /* ensure hash is valid */ X509_check_purpose((X509 *)a, -1, 0); X509_check_purpose((X509 *)b, -1, 0); rv = OPENSSL_memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH); if (rv) return rv; /* Check for match against stored encoding too */ if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) { rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len); if (rv) return rv; return OPENSSL_memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc, a->cert_info->enc.len); } return rv; }
static int check_test(const void *expected, const void *actual, size_t expected_len, const char *name) { if (OPENSSL_memcmp(actual, expected, expected_len) != 0) { printf("%s failed.\nExpected: ", name); hexdump(expected, expected_len); printf("\nCalculated: "); hexdump(actual, expected_len); printf("\n"); return 0; } return 1; }
int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len, RSA *rsa) { if (rsa->n == NULL || rsa->e == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING); return 0; } const size_t rsa_size = RSA_size(rsa); uint8_t *buf = NULL; int ret = 0; uint8_t *signed_msg = NULL; size_t signed_msg_len = 0, len; int signed_msg_is_alloced = 0; if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) { OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } buf = OPENSSL_malloc(rsa_size); if (!buf) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); return 0; } if (!RSA_verify_raw(rsa, &len, buf, rsa_size, sig, sig_len, RSA_PKCS1_PADDING)) { goto out; } if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len, &signed_msg_is_alloced, hash_nid, msg, msg_len)) { goto out; } /* Check that no other information follows the hash value (FIPS 186-4 Section * 5.5) and it matches the expected hash. */ if (len != signed_msg_len || OPENSSL_memcmp(buf, signed_msg, len) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE); goto out; } ret = 1; out: OPENSSL_free(buf); if (signed_msg_is_alloced) { OPENSSL_free(signed_msg); } return ret; }
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 ssl_cert_check_digital_signature_key_usage(const CBS *in) { CBS buf = *in; CBS tbs_cert, outer_extensions; int has_extensions; if (!ssl_cert_skip_to_spki(&buf, &tbs_cert) || /* subjectPublicKeyInfo */ !CBS_get_asn1(&tbs_cert, NULL, CBS_ASN1_SEQUENCE) || /* issuerUniqueID */ !CBS_get_optional_asn1( &tbs_cert, NULL, NULL, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1) || /* subjectUniqueID */ !CBS_get_optional_asn1( &tbs_cert, NULL, NULL, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2) || !CBS_get_optional_asn1( &tbs_cert, &outer_extensions, &has_extensions, CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3)) { goto parse_err; } if (!has_extensions) { return 1; } CBS extensions; if (!CBS_get_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) { goto parse_err; } while (CBS_len(&extensions) > 0) { CBS extension, oid, contents; if (!CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) || (CBS_peek_asn1_tag(&extension, CBS_ASN1_BOOLEAN) && !CBS_get_asn1(&extension, NULL, CBS_ASN1_BOOLEAN)) || !CBS_get_asn1(&extension, &contents, CBS_ASN1_OCTETSTRING) || CBS_len(&extension) != 0) { goto parse_err; } static const uint8_t kKeyUsageOID[3] = {0x55, 0x1d, 0x0f}; if (CBS_len(&oid) != sizeof(kKeyUsageOID) || OPENSSL_memcmp(CBS_data(&oid), kKeyUsageOID, sizeof(kKeyUsageOID)) != 0) { continue; } CBS bit_string; if (!CBS_get_asn1(&contents, &bit_string, CBS_ASN1_BITSTRING) || CBS_len(&contents) != 0) { goto parse_err; } /* This is the KeyUsage extension. See * https://tools.ietf.org/html/rfc5280#section-4.2.1.3 */ if (!CBS_is_valid_asn1_bitstring(&bit_string)) { goto parse_err; } if (!CBS_asn1_bitstring_has_bit(&bit_string, 0)) { OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING); return 0; } return 1; } /* No KeyUsage extension found. */ return 1; parse_err: OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT); return 0; }
int X509_CRL_match(const X509_CRL *a, const X509_CRL *b) { return OPENSSL_memcmp(a->sha1_hash, b->sha1_hash, 20); }
static int CRYPTO_BUFFER_cmp(const CRYPTO_BUFFER *a, const CRYPTO_BUFFER *b) { if (a->len != b->len) { return 1; } return OPENSSL_memcmp(a->data, b->data, a->len); }
static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) { size_t b_len = strlen(b); return a->len == b_len && OPENSSL_memcmp(a->data, b, b_len) == 0; }
/* is_eoc returns true if |header_len| and |contents|, as returned by * |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */ static char is_eoc(size_t header_len, CBS *contents) { return header_len == 2 && CBS_len(contents) == 2 && OPENSSL_memcmp(CBS_data(contents), "\x00\x00", 2) == 0; }
static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; SSL_CLIENT_HELLO client_hello; if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg, ssl->init_num)) { OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); return ssl_hs_error; } uint8_t alert = SSL_AD_DECODE_ERROR; SSL_SESSION *session = NULL; switch (select_session(hs, &alert, &session, &ssl->s3->ticket_age_skew, &client_hello)) { case ssl_ticket_aead_ignore_ticket: assert(session == NULL); if (!ssl_get_new_session(hs, 1 /* server */)) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } break; case ssl_ticket_aead_success: /* Carry over authentication information from the previous handshake into * a fresh session. */ hs->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY); if (/* Early data must be acceptable for this ticket. */ ssl->cert->enable_early_data && session->ticket_max_early_data != 0 && /* The client must have offered early data. */ hs->early_data_offered && /* Channel ID is incompatible with 0-RTT. */ !ssl->s3->tlsext_channel_id_valid && /* The negotiated ALPN must match the one in the ticket. */ ssl->s3->alpn_selected_len == session->early_alpn_len && OPENSSL_memcmp(ssl->s3->alpn_selected, session->early_alpn, ssl->s3->alpn_selected_len) == 0) { ssl->early_data_accepted = 1; } SSL_SESSION_free(session); if (hs->new_session == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } ssl->s3->session_reused = 1; /* Resumption incorporates fresh key material, so refresh the timeout. */ ssl_session_renew_timeout(ssl, hs->new_session, ssl->session_ctx->session_psk_dhe_timeout); break; case ssl_ticket_aead_error: ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); return ssl_hs_error; case ssl_ticket_aead_retry: hs->tls13_state = state_select_session; return ssl_hs_pending_ticket; } /* Record connection properties in the new session. */ hs->new_session->cipher = hs->new_cipher; if (hs->hostname != NULL) { OPENSSL_free(hs->new_session->tlsext_hostname); hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname); if (hs->new_session->tlsext_hostname == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } } /* Store the initial negotiated ALPN in the session. */ if (ssl->s3->alpn_selected != NULL) { hs->new_session->early_alpn = BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len); if (hs->new_session->early_alpn == NULL) { ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } hs->new_session->early_alpn_len = ssl->s3->alpn_selected_len; } if (ssl->ctx->dos_protection_cb != NULL && ssl->ctx->dos_protection_cb(&client_hello) == 0) { /* Connection rejected for DOS reasons. */ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); return ssl_hs_error; } /* Incorporate the PSK into the running secret. */ if (ssl->s3->session_reused) { if (!tls13_advance_key_schedule(hs, hs->new_session->master_key, hs->new_session->master_key_length)) { return ssl_hs_error; } } else if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len)) { return ssl_hs_error; } if (ssl->early_data_accepted) { if (!tls13_derive_early_secrets(hs)) { return ssl_hs_error; } } else if (hs->early_data_offered) { ssl->s3->skip_early_data = 1; } ssl->method->received_flight(ssl); /* Resolve ECDHE and incorporate it into the secret. */ int need_retry; if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) { if (need_retry) { ssl->early_data_accepted = 0; ssl->s3->skip_early_data = 1; hs->tls13_state = state_send_hello_retry_request; return ssl_hs_ok; } return ssl_hs_error; } hs->tls13_state = state_send_server_hello; return ssl_hs_ok; }
int SM2_do_decrypt(const EVP_MD *md, const SM2CiphertextValue *cv, unsigned char *out, size_t *outlen, EC_KEY *ec_key) { int ret = 0; const EC_GROUP *group; const BIGNUM *pri_key; KDF_FUNC kdf; EC_POINT *point = NULL; EC_POINT *tmp_point = NULL; BIGNUM *n = NULL; BIGNUM *h = NULL; BN_CTX *bn_ctx = NULL; EVP_MD_CTX *md_ctx = NULL; unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1]; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen = sizeof(mac); int nbytes, len, i; /* check arguments */ if (!md || !cv || !outlen || !ec_key) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!(kdf = KDF_get_x9_63(md))) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_DIGEST_ALGOR); return 0; } if (!cv->xCoordinate || !cv->yCoordinate || !cv->hash || !cv->ciphertext) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); return 0; } if (cv->hash->length != EVP_MD_size(md)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); return 0; } if (cv->ciphertext->length < SM2_MIN_PLAINTEXT_LENGTH || cv->ciphertext->length > SM2_MAX_PLAINTEXT_LENGTH) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); return 0; } if (!(group = EC_KEY_get0_group(ec_key)) || !(pri_key = EC_KEY_get0_private_key(ec_key))) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_EC_KEY); return 0; } if (!out) { *outlen = cv->ciphertext->length; return 1; } if (*outlen < cv->ciphertext->length) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_BUFFER_TOO_SMALL); return 0; } /* malloc */ point = EC_POINT_new(group); tmp_point = EC_POINT_new(group); n = BN_new(); h = BN_new(); bn_ctx = BN_CTX_new(); md_ctx = EVP_MD_CTX_new(); if (!point || !n || !h || !bn_ctx || !md_ctx) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_MALLOC_FAILURE); goto end; } /* init ec domain parameters */ if (!EC_GROUP_get_order(group, n, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } if (!EC_GROUP_get_cofactor(group, h, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } nbytes = (EC_GROUP_get_degree(group) + 7) / 8; /* get x/yCoordinates as C1 = (x1, y1) */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_set_affine_coordinates_GFp(group, point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } } else { if (!EC_POINT_set_affine_coordinates_GF2m(group, point, cv->xCoordinate, cv->yCoordinate, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } } /* check [h]C1 != O */ if (!EC_POINT_mul(group, tmp_point, NULL, point, h, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } if (EC_POINT_is_at_infinity(group, tmp_point)) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } /* compute ECDH [d]C1 = (x2, y2) */ if (!EC_POINT_mul(group, point, NULL, point, pri_key, bn_ctx)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } if (!(len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EC_LIB); goto end; } /* compute t = KDF(x2 || y2, clen) */ *outlen = cv->ciphertext->length; kdf(buf + 1, len - 1, out, outlen); /* compute M = C2 xor t */ for (i = 0; i < cv->ciphertext->length; i++) { out[i] ^= cv->ciphertext->data[i]; } /* check hash == Hash(x2 || M || y2) */ if (!EVP_DigestInit_ex(md_ctx, md, NULL) || !EVP_DigestUpdate(md_ctx, buf + 1, nbytes) || !EVP_DigestUpdate(md_ctx, out, *outlen) || !EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes) || !EVP_DigestFinal_ex(md_ctx, mac, &maclen)) { SM2err(SM2_F_SM2_DO_DECRYPT, ERR_R_EVP_LIB); goto end; } if (OPENSSL_memcmp(cv->hash->data, mac, maclen) != 0) { SM2err(SM2_F_SM2_DO_DECRYPT, SM2_R_INVALID_CIPHERTEXT); goto end; } ret = 1; end: EC_POINT_free(point); EC_POINT_free(tmp_point); BN_free(n); BN_free(h); BN_CTX_free(bn_ctx); EVP_MD_CTX_free(md_ctx); return ret; }