int main(int argc, char *argv[]) { #ifndef OPENSSL_NO_CRYPTO_MDEBUG char *p; char *lost; int noleak; p = getenv("OPENSSL_DEBUG_MEMORY"); if (p != NULL && strcmp(p, "on") == 0) CRYPTO_set_mem_debug(1); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); lost = OPENSSL_malloc(3); if (!TEST_ptr(lost)) return EXIT_FAILURE; if (argv[1] && strcmp(argv[1], "freeit") == 0) { OPENSSL_free(lost); lost = NULL; } noleak = CRYPTO_mem_leaks_fp(stderr); /* If -1 return value something bad happened */ if (!TEST_int_ne(noleak, -1)) return EXIT_FAILURE; return TEST_int_eq(lost != NULL, noleak == 0) ? EXIT_SUCCESS : EXIT_FAILURE; #else return EXIT_SUCCESS; #endif }
static int test_tbl_standard(void) { const ASN1_STRING_TABLE *tmp; int last_nid = -1; size_t i; for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++) { if (tmp->nid < last_nid) { last_nid = 0; break; } last_nid = tmp->nid; } if (TEST_int_ne(last_nid, 0)) { TEST_info("asn1 tbl_standard: Table order OK"); return 1; } TEST_info("asn1 tbl_standard: out of order"); for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++) TEST_note("asn1 tbl_standard: Index %zu, NID %d, Name=%s", i, tmp->nid, OBJ_nid2ln(tmp->nid)); return 0; }
static int test_property_string(void) { OSSL_METHOD_STORE *store; int res = 0; OSSL_PROPERTY_IDX i, j; if (TEST_ptr(store = ossl_method_store_new(NULL)) && TEST_int_eq(ossl_property_name(NULL, "fnord", 0), 0) && TEST_int_ne(ossl_property_name(NULL, "fnord", 1), 0) && TEST_int_ne(ossl_property_name(NULL, "name", 1), 0) /* Property value checks */ && TEST_int_eq(ossl_property_value(NULL, "fnord", 0), 0) && TEST_int_ne(i = ossl_property_value(NULL, "no", 0), 0) && TEST_int_ne(j = ossl_property_value(NULL, "yes", 0), 0) && TEST_int_ne(i, j) && TEST_int_eq(ossl_property_value(NULL, "yes", 1), j) && TEST_int_eq(ossl_property_value(NULL, "no", 1), i) && TEST_int_ne(i = ossl_property_value(NULL, "illuminati", 1), 0) && TEST_int_eq(j = ossl_property_value(NULL, "fnord", 1), i + 1) && TEST_int_eq(ossl_property_value(NULL, "fnord", 1), j) /* Check name and values are distinct */ && TEST_int_eq(ossl_property_value(NULL, "cold", 0), 0) && TEST_int_ne(ossl_property_name(NULL, "fnord", 0), ossl_property_value(NULL, "fnord", 0))) res = 1; ossl_method_store_free(store); return res; }
static int add_property_names(const char *n, ...) { va_list args; int res = 1; va_start(args, n); do { if (!TEST_int_ne(ossl_property_name(NULL, n, 1), 0)) res = 0; } while ((n = va_arg(args, const char *)) != NULL); va_end(args); return res; }
static int test_is_composite_enhanced(int id) { int ret; int status = 0; BIGNUM *bn = NULL; ret = TEST_ptr(bn = BN_new()) /* negative tests for different composite numbers */ && TEST_true(BN_set_word(bn, composites[id])) && TEST_true(bn_miller_rabin_is_prime(bn, 10, ctx, NULL, 1, &status)) && TEST_int_ne(status, BN_PRIMETEST_PROBABLY_PRIME); BN_free(bn); return ret; }
static int test_standard_methods(void) { const EVP_PKEY_ASN1_METHOD **tmp; int last_pkey_id = -1; size_t i; int ok = 1; for (tmp = standard_methods, i = 0; i < OSSL_NELEM(standard_methods); i++, tmp++) { if ((*tmp)->pkey_id < last_pkey_id) { last_pkey_id = 0; break; } last_pkey_id = (*tmp)->pkey_id; /* * One of the following must be true: * * pem_str == NULL AND ASN1_PKEY_ALIAS is set * pem_str != NULL AND ASN1_PKEY_ALIAS is clear * * Anything else is an error and may lead to a corrupt ASN1 method table */ if (!TEST_true(((*tmp)->pem_str == NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) != 0) || ((*tmp)->pem_str != NULL && ((*tmp)->pkey_flags & ASN1_PKEY_ALIAS) == 0))) { TEST_note("asn1 standard methods: Index %zu, pkey ID %d, Name=%s", i, (*tmp)->pkey_id, OBJ_nid2sn((*tmp)->pkey_id)); ok = 0; } } if (TEST_int_ne(last_pkey_id, 0)) { TEST_info("asn1 standard methods: Table order OK"); return ok; } TEST_note("asn1 standard methods: out of order"); for (tmp = standard_methods, i = 0; i < OSSL_NELEM(standard_methods); i++, tmp++) TEST_note("asn1 standard methods: Index %zu, pkey ID %d, Name=%s", i, (*tmp)->pkey_id, OBJ_nid2sn((*tmp)->pkey_id)); return 0; }
static int test_builtin(void) { EC_builtin_curve *curves = NULL; size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; ECDSA_SIG *ecdsa_sig = NULL, *modified_sig = NULL; unsigned char digest[20], wrong_digest[20]; unsigned char *signature = NULL; const unsigned char *sig_ptr; unsigned char *sig_ptr2; unsigned char *raw_buf = NULL; const BIGNUM *sig_r, *sig_s; BIGNUM *modified_r = NULL, *modified_s = NULL; BIGNUM *unmodified_r = NULL, *unmodified_s = NULL; unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ if (!TEST_true(RAND_bytes(digest, 20)) || !TEST_true(RAND_bytes(wrong_digest, 20))) goto builtin_err; /* create and verify a ecdsa signature with every available curve */ /* get a list of all internal curves */ crv_len = EC_get_builtin_curves(NULL, 0); if (!TEST_ptr(curves = OPENSSL_malloc(sizeof(*curves) * crv_len)) || !TEST_true(EC_get_builtin_curves(curves, crv_len))) goto builtin_err; /* now create and verify a signature for every curve */ for (n = 0; n < crv_len; n++) { unsigned char dirt, offset; nid = curves[n].nid; if (nid == NID_ipsec4 || nid == NID_X25519) continue; /* create new ecdsa key (== EC_KEY) */ if (!TEST_ptr(eckey = EC_KEY_new()) || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) || !TEST_true(EC_KEY_set_group(eckey, group))) goto builtin_err; EC_GROUP_free(group); degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); if (degree < 160) { /* drop the curve */ EC_KEY_free(eckey); eckey = NULL; continue; } TEST_info("testing %s", OBJ_nid2sn(nid)); /* create key */ if (!TEST_true(EC_KEY_generate_key(eckey))) goto builtin_err; /* create second key */ if (!TEST_ptr(wrong_eckey = EC_KEY_new()) || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) || !TEST_true(EC_KEY_set_group(wrong_eckey, group))) goto builtin_err; EC_GROUP_free(group); if (!TEST_true(EC_KEY_generate_key(wrong_eckey))) goto builtin_err; /* check key */ if (!TEST_true(EC_KEY_check_key(eckey))) goto builtin_err; /* create signature */ sig_len = ECDSA_size(eckey); if (!TEST_ptr(signature = OPENSSL_malloc(sig_len)) || !TEST_true(ECDSA_sign(0, digest, 20, signature, &sig_len, eckey))) goto builtin_err; /* verify signature */ if (!TEST_int_eq(ECDSA_verify(0, digest, 20, signature, sig_len, eckey), 1)) goto builtin_err; /* verify signature with the wrong key */ if (!TEST_int_ne(ECDSA_verify(0, digest, 20, signature, sig_len, wrong_eckey), 1)) goto builtin_err; /* wrong digest */ if (!TEST_int_ne(ECDSA_verify(0, wrong_digest, 20, signature, sig_len, eckey), 1)) goto builtin_err; /* wrong length */ if (!TEST_int_ne(ECDSA_verify(0, digest, 20, signature, sig_len - 1, eckey), 1)) goto builtin_err; /* * Modify a single byte of the signature: to ensure we don't garble * the ASN1 structure, we read the raw signature and modify a byte in * one of the bignums directly. */ sig_ptr = signature; if (!TEST_ptr(ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len))) goto builtin_err; ECDSA_SIG_get0(ecdsa_sig, &sig_r, &sig_s); /* Store the two BIGNUMs in raw_buf. */ r_len = BN_num_bytes(sig_r); s_len = BN_num_bytes(sig_s); bn_len = (degree + 7) / 8; if (!TEST_false(r_len > bn_len) || !TEST_false(s_len > bn_len)) goto builtin_err; buf_len = 2 * bn_len; if (!TEST_ptr(raw_buf = OPENSSL_zalloc(buf_len))) goto builtin_err; BN_bn2bin(sig_r, raw_buf + bn_len - r_len); BN_bn2bin(sig_s, raw_buf + buf_len - s_len); /* Modify a single byte in the buffer. */ offset = raw_buf[10] % buf_len; dirt = raw_buf[11] ? raw_buf[11] : 1; raw_buf[offset] ^= dirt; /* Now read the BIGNUMs back in from raw_buf. */ if (!TEST_ptr(modified_sig = ECDSA_SIG_new())) goto builtin_err; if (!TEST_ptr(modified_r = BN_bin2bn(raw_buf, bn_len, NULL)) || !TEST_ptr(modified_s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) || !TEST_true(ECDSA_SIG_set0(modified_sig, modified_r, modified_s))) { BN_free(modified_r); BN_free(modified_s); goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(modified_sig, &sig_ptr2); if (!TEST_false(ECDSA_verify(0, digest, 20, signature, sig_len, eckey))) goto builtin_err; /* Sanity check: undo the modification and verify signature. */ raw_buf[offset] ^= dirt; if (!TEST_ptr(unmodified_r = BN_bin2bn(raw_buf, bn_len, NULL)) || !TEST_ptr(unmodified_s = BN_bin2bn(raw_buf + bn_len, bn_len, NULL)) || !TEST_true(ECDSA_SIG_set0(modified_sig, unmodified_r, unmodified_s))) { BN_free(unmodified_r); BN_free(unmodified_s); goto builtin_err; } sig_ptr2 = signature; sig_len = i2d_ECDSA_SIG(modified_sig, &sig_ptr2); if (!TEST_true(ECDSA_verify(0, digest, 20, signature, sig_len, eckey))) goto builtin_err; /* cleanup */ ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; ECDSA_SIG_free(ecdsa_sig); ecdsa_sig = NULL; ECDSA_SIG_free(modified_sig); modified_sig = NULL; OPENSSL_free(raw_buf); raw_buf = NULL; } ret = 1; builtin_err: EC_KEY_free(eckey); EC_KEY_free(wrong_eckey); ECDSA_SIG_free(ecdsa_sig); ECDSA_SIG_free(modified_sig); OPENSSL_free(signature); OPENSSL_free(raw_buf); OPENSSL_free(curves); return ret; }
static int rfc5114_test(void) { int i; DH *dhA = NULL; DH *dhB = NULL; unsigned char *Z1 = NULL; unsigned char *Z2 = NULL; const rfc5114_td *td = NULL; BIGNUM *bady = NULL, *priv_key = NULL, *pub_key = NULL; const BIGNUM *pub_key_tmp; for (i = 0; i < (int)OSSL_NELEM(rfctd); i++) { td = rfctd + i; /* Set up DH structures setting key components */ if (!TEST_ptr(dhA = td->get_param()) || !TEST_ptr(dhB = td->get_param())) goto bad_err; if (!TEST_ptr(priv_key = BN_bin2bn(td->xA, td->xA_len, NULL)) || !TEST_ptr(pub_key = BN_bin2bn(td->yA, td->yA_len, NULL)) || !TEST_true(DH_set0_key(dhA, pub_key, priv_key))) goto bad_err; if (!TEST_ptr(priv_key = BN_bin2bn(td->xB, td->xB_len, NULL)) || !TEST_ptr(pub_key = BN_bin2bn(td->yB, td->yB_len, NULL)) || !TEST_true( DH_set0_key(dhB, pub_key, priv_key))) goto bad_err; priv_key = pub_key = NULL; if (!TEST_uint_eq(td->Z_len, (size_t)DH_size(dhA)) || !TEST_uint_eq(td->Z_len, (size_t)DH_size(dhB))) goto err; if (!TEST_ptr(Z1 = OPENSSL_malloc(DH_size(dhA))) || !TEST_ptr(Z2 = OPENSSL_malloc(DH_size(dhB)))) goto bad_err; /* * Work out shared secrets using both sides and compare with expected * values. */ DH_get0_key(dhB, &pub_key_tmp, NULL); if (!TEST_int_ne(DH_compute_key(Z1, pub_key_tmp, dhA), -1)) goto bad_err; DH_get0_key(dhA, &pub_key_tmp, NULL); if (!TEST_int_ne(DH_compute_key(Z2, pub_key_tmp, dhB), -1)) goto bad_err; if (!TEST_mem_eq(Z1, td->Z_len, td->Z, td->Z_len) || !TEST_mem_eq(Z2, td->Z_len, td->Z, td->Z_len)) goto err; DH_free(dhA); dhA = NULL; DH_free(dhB); dhB = NULL; OPENSSL_free(Z1); Z1 = NULL; OPENSSL_free(Z2); Z2 = NULL; } /* Now i == OSSL_NELEM(rfctd) */ /* RFC5114 uses unsafe primes, so now test an invalid y value */ if (!TEST_ptr(dhA = DH_get_2048_224()) || !TEST_ptr(Z1 = OPENSSL_malloc(DH_size(dhA)))) goto bad_err; if (!TEST_ptr(bady = BN_bin2bn(dhtest_rfc5114_2048_224_bad_y, sizeof(dhtest_rfc5114_2048_224_bad_y), NULL))) goto bad_err; if (!DH_generate_key(dhA)) goto bad_err; if (DH_compute_key(Z1, bady, dhA) != -1) { /* * DH_compute_key should fail with -1. If we get here we unexpectedly * allowed an invalid y value */ goto err; } /* We'll have a stale error on the queue from the above test so clear it */ ERR_clear_error(); BN_free(bady); DH_free(dhA); OPENSSL_free(Z1); return 1; bad_err: BN_free(bady); DH_free(dhA); DH_free(dhB); BN_free(pub_key); BN_free(priv_key); OPENSSL_free(Z1); OPENSSL_free(Z2); TEST_error("Initialisation error RFC5114 set %d\n", i + 1); return 0; err: BN_free(bady); DH_free(dhA); DH_free(dhB); OPENSSL_free(Z1); OPENSSL_free(Z2); TEST_error("Test failed RFC5114 set %d\n", i + 1); return 0; }
/*- * Positive and negative ECDSA testing through EVP interface: * - EVP_DigestSign (this is the one-shot version) * - EVP_DigestVerify * * Tests the library can successfully: * - create a key * - create a signature * - accept that signature * - reject that signature with a different public key * - reject that signature if its length is not correct * - reject that signature after modifying the message * - accept that signature after un-modifying the message * - reject that signature after modifying the signature * - accept that signature after un-modifying the signature */ static int test_builtin(int n) { EC_KEY *eckey_neg = NULL, *eckey = NULL; unsigned char dirt, offset, tbs[128]; unsigned char *sig = NULL; EVP_PKEY *pkey_neg = NULL, *pkey = NULL; EVP_MD_CTX *mctx = NULL; size_t sig_len; int nid, ret = 0; nid = curves[n].nid; /* skip built-in curves where ord(G) is not prime */ if (nid == NID_ipsec4 || nid == NID_ipsec3) { TEST_info("skipped: ECDSA unsupported for curve %s", OBJ_nid2sn(nid)); return 1; } TEST_info("testing ECDSA for curve %s", OBJ_nid2sn(nid)); if (!TEST_ptr(mctx = EVP_MD_CTX_new()) /* get some random message data */ || !TEST_true(RAND_bytes(tbs, sizeof(tbs))) /* real key */ || !TEST_ptr(eckey = EC_KEY_new_by_curve_name(nid)) || !TEST_true(EC_KEY_generate_key(eckey)) || !TEST_ptr(pkey = EVP_PKEY_new()) || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey, eckey)) /* fake key for negative testing */ || !TEST_ptr(eckey_neg = EC_KEY_new_by_curve_name(nid)) || !TEST_true(EC_KEY_generate_key(eckey_neg)) || !TEST_ptr(pkey_neg = EVP_PKEY_new()) || !TEST_true(EVP_PKEY_assign_EC_KEY(pkey_neg, eckey_neg))) goto err; sig_len = ECDSA_size(eckey); if (!TEST_ptr(sig = OPENSSL_malloc(sig_len)) /* create a signature */ || !TEST_true(EVP_DigestSignInit(mctx, NULL, NULL, NULL, pkey)) || !TEST_true(EVP_DigestSign(mctx, sig, &sig_len, tbs, sizeof(tbs))) || !TEST_int_le(sig_len, ECDSA_size(eckey)) /* negative test, verify with wrong key, 0 return */ || !TEST_true(EVP_MD_CTX_reset(mctx)) || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey_neg)) || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 0) /* negative test, verify with wrong signature length, -1 return */ || !TEST_true(EVP_MD_CTX_reset(mctx)) || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey)) || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len - 1, tbs, sizeof(tbs)), -1) /* positive test, verify with correct key, 1 return */ || !TEST_true(EVP_MD_CTX_reset(mctx)) || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey)) || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1)) goto err; /* muck with the message, test it fails with 0 return */ tbs[0] ^= 1; if (!TEST_true(EVP_MD_CTX_reset(mctx)) || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey)) || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 0)) goto err; /* un-muck and test it verifies */ tbs[0] ^= 1; if (!TEST_true(EVP_MD_CTX_reset(mctx)) || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey)) || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1)) goto err; /*- * Muck with the ECDSA signature. The DER encoding is one of: * - 30 LL 02 .. * - 30 81 LL 02 .. * * - Sometimes this mucks with the high level DER sequence wrapper: * in that case, DER-parsing of the whole signature should fail. * * - Sometimes this mucks with the DER-encoding of ECDSA.r: * in that case, DER-parsing of ECDSA.r should fail. * * - Sometimes this mucks with the DER-encoding of ECDSA.s: * in that case, DER-parsing of ECDSA.s should fail. * * - Sometimes this mucks with ECDSA.r: * in that case, the signature verification should fail. * * - Sometimes this mucks with ECDSA.s: * in that case, the signature verification should fail. * * The usual case is changing the integer value of ECDSA.r or ECDSA.s. * Because the ratio of DER overhead to signature bytes is small. * So most of the time it will be one of the last two cases. * * In any case, EVP_PKEY_verify should not return 1 for valid. */ offset = tbs[0] % sig_len; dirt = tbs[1] ? tbs[1] : 1; sig[offset] ^= dirt; if (!TEST_true(EVP_MD_CTX_reset(mctx)) || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey)) || !TEST_int_ne(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1)) goto err; /* un-muck and test it verifies */ sig[offset] ^= dirt; if (!TEST_true(EVP_MD_CTX_reset(mctx)) || !TEST_true(EVP_DigestVerifyInit(mctx, NULL, NULL, NULL, pkey)) || !TEST_int_eq(EVP_DigestVerify(mctx, sig, sig_len, tbs, sizeof(tbs)), 1)) goto err; ret = 1; err: EVP_PKEY_free(pkey); EVP_PKEY_free(pkey_neg); EVP_MD_CTX_free(mctx); OPENSSL_free(sig); return ret; }