X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=test%2Fevp_test.c;h=be18afb63d55ff7e9d75ad4a6b9f29239468b792;hb=2bdb4af50364121a5f0e47024e9f71e1a6025fcf;hp=860fcc878e653fdd69cc42e749593dc906798419;hpb=9442c8d7636a2bb257e76d4137a5d7305dedf28f;p=openssl.git diff --git a/test/evp_test.c b/test/evp_test.c index 860fcc878e..be18afb63d 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -73,6 +73,29 @@ static KEY_LIST *public_keys; static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst); static int parse_bin(const char *value, unsigned char **buf, size_t *buflen); +static int pkey_test_ctrl(EVP_TEST *t, EVP_PKEY_CTX *pctx, + const char *value); + +/* + * Compare two memory regions for equality, returning zero if they differ. + * However, if there is expected to be an error and the actual error + * matches then the memory is expected to be different so handle this + * case without producing unnecessary test framework output. + */ +static int memory_err_compare(EVP_TEST *t, const char *err, + const void *expected, size_t expected_len, + const void *got, size_t got_len) +{ + int r; + + if (t->expected_err != NULL && strcmp(t->expected_err, err) == 0) + r = !TEST_mem_ne(expected, expected_len, got, got_len); + else + r = TEST_mem_eq(expected, expected_len, got, got_len); + if (!r) + t->err = err; + return r; +} /* * Structure used to hold a list of blocks of memory to test @@ -397,10 +420,11 @@ static int digest_test_run(EVP_TEST *t) t->err = "DIGEST_LENGTH_MISMATCH"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "DIGEST_MISMATCH"; + if (!memory_err_compare(t, "DIGEST_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: @@ -435,7 +459,7 @@ typedef struct cipher_data_st { size_t plaintext_len; unsigned char *ciphertext; size_t ciphertext_len; - /* GCM, CCM only */ + /* GCM, CCM and OCB only */ unsigned char *aad; size_t aad_len; unsigned char *tag; @@ -463,7 +487,7 @@ static int cipher_test_init(EVP_TEST *t, const char *alg) if (m == EVP_CIPH_GCM_MODE || m == EVP_CIPH_OCB_MODE || m == EVP_CIPH_CCM_MODE) - cdat->aead = EVP_CIPHER_mode(cipher); + cdat->aead = m; else if (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) cdat->aead = -1; else @@ -688,11 +712,9 @@ static int cipher_test_enc(EVP_TEST *t, int enc, t->err = "CIPHERFINAL_ERROR"; goto err; } - if (!TEST_mem_eq(expected_out, out_len, - tmp + out_misalign, tmplen + tmpflen)) { - t->err = "VALUE_MISMATCH"; + if (!memory_err_compare(t, "VALUE_MISMATCH", expected_out, out_len, + tmp + out_misalign, tmplen + tmpflen)) goto err; - } if (enc && expected->aead) { unsigned char rtag[16]; @@ -705,11 +727,10 @@ static int cipher_test_enc(EVP_TEST *t, int enc, t->err = "TAG_RETRIEVE_ERROR"; goto err; } - if (!TEST_mem_eq(expected->tag, expected->tag_len, - rtag, expected->tag_len)) { - t->err = "TAG_VALUE_MISMATCH"; + if (!memory_err_compare(t, "TAG_VALUE_MISMATCH", + expected->tag, expected->tag_len, + rtag, expected->tag_len)) goto err; - } } t->err = NULL; ok = 1; @@ -811,8 +832,9 @@ static const EVP_TEST_METHOD cipher_test_method = { **/ typedef struct mac_data_st { - /* MAC type */ - int type; + /* MAC type in one form or another */ + const EVP_MAC *mac; /* for mac_test_run_mac */ + int type; /* for mac_test_run_pkey */ /* Algorithm string for this MAC */ char *alg; /* MAC key */ @@ -824,49 +846,84 @@ typedef struct mac_data_st { /* Expected output */ unsigned char *output; size_t output_len; + /* Collection of controls */ + STACK_OF(OPENSSL_STRING) *controls; } MAC_DATA; static int mac_test_init(EVP_TEST *t, const char *alg) { - int type; + const EVP_MAC *mac = NULL; + int type = NID_undef; MAC_DATA *mdat; - if (strcmp(alg, "HMAC") == 0) { - type = EVP_PKEY_HMAC; - } else if (strcmp(alg, "CMAC") == 0) { + if ((mac = EVP_get_macbyname(alg)) == NULL) { + /* + * Since we didn't find an EVP_MAC, we check for known EVP_PKEY methods + * For debugging purposes, we allow 'NNNN by EVP_PKEY' to force running + * the EVP_PKEY method. + */ + size_t sz = strlen(alg); + static const char epilogue[] = " by EVP_PKEY"; + + if (strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0) + sz -= sizeof(epilogue) - 1; + + if (strncmp(alg, "HMAC", sz) == 0) { + type = EVP_PKEY_HMAC; + } else if (strncmp(alg, "CMAC", sz) == 0) { #ifndef OPENSSL_NO_CMAC - type = EVP_PKEY_CMAC; + type = EVP_PKEY_CMAC; #else - t->skip = 1; - return 1; + t->skip = 1; + return 1; #endif - } else if (strcmp(alg, "Poly1305") == 0) { + } else if (strncmp(alg, "Poly1305", sz) == 0) { #ifndef OPENSSL_NO_POLY1305 - type = EVP_PKEY_POLY1305; + type = EVP_PKEY_POLY1305; #else - t->skip = 1; - return 1; + t->skip = 1; + return 1; #endif - } else if (strcmp(alg, "SipHash") == 0) { + } else if (strncmp(alg, "SipHash", sz) == 0) { #ifndef OPENSSL_NO_SIPHASH - type = EVP_PKEY_SIPHASH; + type = EVP_PKEY_SIPHASH; #else - t->skip = 1; - return 1; + t->skip = 1; + return 1; #endif - } else - return 0; + } else { + /* + * Not a known EVP_PKEY method either. If it's a known OID, then + * assume it's been disabled. + */ + if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) { + t->skip = 1; + return 1; + } + + return 0; + } + } mdat = OPENSSL_zalloc(sizeof(*mdat)); mdat->type = type; + mdat->mac = mac; + mdat->controls = sk_OPENSSL_STRING_new_null(); t->data = mdat; return 1; } +/* Because OPENSSL_free is a macro, it can't be passed as a function pointer */ +static void openssl_free(char *m) +{ + OPENSSL_free(m); +} + static void mac_test_cleanup(EVP_TEST *t) { MAC_DATA *mdat = t->data; + sk_OPENSSL_STRING_pop_free(mdat->controls, openssl_free); OPENSSL_free(mdat->alg); OPENSSL_free(mdat->key); OPENSSL_free(mdat->input); @@ -890,10 +947,13 @@ static int mac_test_parse(EVP_TEST *t, return parse_bin(value, &mdata->input, &mdata->input_len); if (strcmp(keyword, "Output") == 0) return parse_bin(value, &mdata->output, &mdata->output_len); + if (strcmp(keyword, "Ctrl") == 0) + return sk_OPENSSL_STRING_push(mdata->controls, + OPENSSL_strdup(value)) != 0; return 0; } -static int mac_test_run(EVP_TEST *t) +static int mac_test_run_pkey(EVP_TEST *t) { MAC_DATA *expected = t->data; EVP_MD_CTX *mctx = NULL; @@ -902,6 +962,13 @@ static int mac_test_run(EVP_TEST *t) const EVP_MD *md = NULL; unsigned char *got = NULL; size_t got_len; + int i; + + if (expected->alg == NULL) + TEST_info("Trying the EVP_PKEY %s test", OBJ_nid2sn(expected->type)); + else + TEST_info("Trying the EVP_PKEY %s test with %s", + OBJ_nid2sn(expected->type), expected->alg); #ifdef OPENSSL_NO_DES if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) { @@ -915,8 +982,8 @@ static int mac_test_run(EVP_TEST *t) key = EVP_PKEY_new_CMAC_key(NULL, expected->key, expected->key_len, EVP_get_cipherbyname(expected->alg)); else - key = EVP_PKEY_new_private_key(expected->type, NULL, expected->key, - expected->key_len); + key = EVP_PKEY_new_raw_private_key(expected->type, NULL, expected->key, + expected->key_len); if (key == NULL) { t->err = "MAC_KEY_CREATE_ERROR"; goto err; @@ -936,7 +1003,12 @@ static int mac_test_run(EVP_TEST *t) t->err = "DIGESTSIGNINIT_ERROR"; goto err; } - + for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) + if (!pkey_test_ctrl(t, pctx, + sk_OPENSSL_STRING_value(expected->controls, i))) { + t->err = "EVPPKEYCTXCTRL_ERROR"; + goto err; + } if (!EVP_DigestSignUpdate(mctx, expected->input, expected->input_len)) { t->err = "DIGESTSIGNUPDATE_ERROR"; goto err; @@ -950,8 +1022,9 @@ static int mac_test_run(EVP_TEST *t) goto err; } if (!EVP_DigestSignFinal(mctx, got, &got_len) - || !TEST_mem_eq(expected->output, expected->output_len, - got, got_len)) { + || !memory_err_compare(t, "TEST_MAC_ERR", + expected->output, expected->output_len, + got, got_len)) { t->err = "TEST_MAC_ERR"; goto err; } @@ -964,6 +1037,126 @@ static int mac_test_run(EVP_TEST *t) return 1; } +static int mac_test_run_mac(EVP_TEST *t) +{ + MAC_DATA *expected = t->data; + EVP_MAC_CTX *ctx = NULL; + const void *algo = NULL; + int algo_ctrl = 0; + unsigned char *got = NULL; + size_t got_len; + int rv, i; + + if (expected->alg == NULL) + TEST_info("Trying the EVP_MAC %s test", EVP_MAC_name(expected->mac)); + else + TEST_info("Trying the EVP_MAC %s test with %s", + EVP_MAC_name(expected->mac), expected->alg); + +#ifdef OPENSSL_NO_DES + if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) { + /* Skip DES */ + t->err = NULL; + goto err; + } +#endif + + if ((ctx = EVP_MAC_CTX_new(expected->mac)) == NULL) { + t->err = "MAC_CREATE_ERROR"; + goto err; + } + + if (expected->alg != NULL + && ((algo_ctrl = EVP_MAC_CTRL_SET_CIPHER, + algo = EVP_get_cipherbyname(expected->alg)) == NULL + && (algo_ctrl = EVP_MAC_CTRL_SET_MD, + algo = EVP_get_digestbyname(expected->alg)) == NULL)) { + t->err = "MAC_BAD_ALGORITHM"; + goto err; + } + + + if (algo_ctrl != 0) { + rv = EVP_MAC_ctrl(ctx, algo_ctrl, algo); + if (rv == -2) { + t->err = "MAC_CTRL_INVALID"; + goto err; + } else if (rv <= 0) { + t->err = "MAC_CTRL_ERROR"; + goto err; + } + } + + rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_KEY, + expected->key, expected->key_len); + if (rv == -2) { + t->err = "MAC_CTRL_INVALID"; + goto err; + } else if (rv <= 0) { + t->err = "MAC_CTRL_ERROR"; + goto err; + } + + if (!EVP_MAC_init(ctx)) { + t->err = "MAC_INIT_ERROR"; + goto err; + } + for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) { + char *p, *tmpval; + char *value = sk_OPENSSL_STRING_value(expected->controls, i); + + if (!TEST_ptr(tmpval = OPENSSL_strdup(value))) { + t->err = "MAC_CTRL_ERROR"; + goto err; + } + p = strchr(tmpval, ':'); + if (p != NULL) + *p++ = '\0'; + rv = EVP_MAC_ctrl_str(ctx, tmpval, p); + OPENSSL_free(tmpval); + if (rv == -2) { + t->err = "MAC_CTRL_INVALID"; + goto err; + } else if (rv <= 0) { + t->err = "MAC_CTRL_ERROR"; + goto err; + } + } + if (!EVP_MAC_update(ctx, expected->input, expected->input_len)) { + t->err = "MAC_UPDATE_ERROR"; + goto err; + } + if (!EVP_MAC_final(ctx, NULL, &got_len)) { + t->err = "MAC_FINAL_LENGTH_ERROR"; + goto err; + } + if (!TEST_ptr(got = OPENSSL_malloc(got_len))) { + t->err = "TEST_FAILURE"; + goto err; + } + if (!EVP_MAC_final(ctx, got, &got_len) + || !memory_err_compare(t, "TEST_MAC_ERR", + expected->output, expected->output_len, + got, got_len)) { + t->err = "TEST_MAC_ERR"; + goto err; + } + t->err = NULL; + err: + EVP_MAC_CTX_free(ctx); + OPENSSL_free(got); + return 1; +} + +static int mac_test_run(EVP_TEST *t) +{ + MAC_DATA *expected = t->data; + + if (expected->mac != NULL) + return mac_test_run_mac(t); + return mac_test_run_pkey(t); +} + static const EVP_TEST_METHOD mac_test_method = { "MAC", mac_test_init, @@ -1108,10 +1301,11 @@ static int pkey_test_run(EVP_TEST *t) t->err = "KEYOP_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "KEYOP_MISMATCH"; + if (!memory_err_compare(t, "KEYOP_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(got); @@ -1226,10 +1420,10 @@ static int pderive_test_run(EVP_TEST *t) t->err = "DERIVE_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "SHARED_SECRET_MISMATCH"; + if (!memory_err_compare(t, "SHARED_SECRET_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } t->err = NULL; err: @@ -1444,11 +1638,10 @@ static int pbe_test_run(EVP_TEST *t) goto err; } } - if (!TEST_mem_eq(expected->key, expected->key_len, - key, expected->key_len)) { - t->err = "KEY_MISMATCH"; + if (!memory_err_compare(t, "KEY_MISMATCH", expected->key, expected->key_len, + key, expected->key_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(key); @@ -1559,11 +1752,10 @@ static int encode_test_run(EVP_TEST *t) EVP_ENCODE_CTX_free(encode_ctx); - if (!TEST_mem_eq(expected->output, expected->output_len, - encode_out, output_len)) { - t->err = "BAD_ENCODING"; + if (!memory_err_compare(t, "BAD_ENCODING", + expected->output, expected->output_len, + encode_out, output_len)) goto err; - } } if (!TEST_ptr(decode_out = @@ -1585,8 +1777,9 @@ static int encode_test_run(EVP_TEST *t) output_len += chunk_len; if (expected->encoding != BASE64_INVALID_ENCODING - && !TEST_mem_eq(expected->input, expected->input_len, - decode_out, output_len)) { + && !memory_err_compare(t, "BAD_DECODING", + expected->input, expected->input_len, + decode_out, output_len)) { t->err = "BAD_DECODING"; goto err; } @@ -1687,10 +1880,11 @@ static int kdf_test_run(EVP_TEST *t) t->err = "KDF_DERIVE_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "KDF_MISMATCH"; + if (!memory_err_compare(t, "KDF_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: @@ -2079,11 +2273,12 @@ static int digestsign_test_run(EVP_TEST *t) t->err = "DIGESTSIGNFINAL_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "SIGNATURE_MISMATCH"; + if (!memory_err_compare(t, "SIGNATURE_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(got); return 1; @@ -2156,11 +2351,12 @@ static int oneshot_digestsign_test_run(EVP_TEST *t) t->err = "DIGESTSIGN_ERROR"; goto err; } - if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) { - t->err = "SIGNATURE_MISMATCH"; + if (!memory_err_compare(t, "SIGNATURE_MISMATCH", + expected->output, expected->output_len, + got, got_len)) goto err; - } + t->err = NULL; err: OPENSSL_free(got); return 1; @@ -2378,7 +2574,7 @@ static void free_key_list(KEY_LIST *lst) /* * Is the key type an unsupported algorithm? */ -static int key_unsupported() +static int key_unsupported(void) { long err = ERR_peek_error(); @@ -2439,20 +2635,65 @@ top: if (strcmp(pp->key, "PrivateKey") == 0) { pkey = PEM_read_bio_PrivateKey(t->s.key, NULL, 0, NULL); if (pkey == NULL && !key_unsupported()) { + EVP_PKEY_free(pkey); TEST_info("Can't read private key %s", pp->value); TEST_openssl_errors(); return 0; } klist = &private_keys; - } - else if (strcmp(pp->key, "PublicKey") == 0) { + } else if (strcmp(pp->key, "PublicKey") == 0) { pkey = PEM_read_bio_PUBKEY(t->s.key, NULL, 0, NULL); if (pkey == NULL && !key_unsupported()) { + EVP_PKEY_free(pkey); TEST_info("Can't read public key %s", pp->value); TEST_openssl_errors(); return 0; } klist = &public_keys; + } else if (strcmp(pp->key, "PrivateKeyRaw") == 0 + || strcmp(pp->key, "PublicKeyRaw") == 0 ) { + char *strnid = NULL, *keydata = NULL; + unsigned char *keybin; + size_t keylen; + int nid; + + if (strcmp(pp->key, "PrivateKeyRaw") == 0) + klist = &private_keys; + else + klist = &public_keys; + + strnid = strchr(pp->value, ':'); + if (strnid != NULL) { + *strnid++ = '\0'; + keydata = strchr(strnid, ':'); + if (keydata != NULL) + *keydata++ = '\0'; + } + if (keydata == NULL) { + TEST_info("Failed to parse %s value", pp->key); + return 0; + } + + nid = OBJ_txt2nid(strnid); + if (nid == NID_undef) { + TEST_info("Uncrecognised algorithm NID"); + return 0; + } + if (!parse_bin(keydata, &keybin, &keylen)) { + TEST_info("Failed to create binary key"); + return 0; + } + if (klist == &private_keys) + pkey = EVP_PKEY_new_raw_private_key(nid, NULL, keybin, keylen); + else + pkey = EVP_PKEY_new_raw_public_key(nid, NULL, keybin, keylen); + if (pkey == NULL && !key_unsupported()) { + TEST_info("Can't read %s data", pp->key); + OPENSSL_free(keybin); + TEST_openssl_errors(); + return 0; + } + OPENSSL_free(keybin); } /* If we have a key add to list */ @@ -2464,6 +2705,17 @@ top: if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key)))) return 0; key->name = take_value(pp); + + /* Hack to detect SM2 keys */ + if(pkey != NULL && strstr(key->name, "SM2") != NULL) { +#ifdef OPENSSL_NO_SM2 + EVP_PKEY_free(pkey); + pkey = NULL; +#else + EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); +#endif + } + key->key = pkey; key->next = *klist; *klist = key;