corecrypto/ccec/crypto_test/crypto_test_ecdsa.c

245 lines
9.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Copyright (c) (2014,2015,2016,2017,2018,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#include "testmore.h"
#include "testbyteBuffer.h"
#include "testccnBuffer.h"
#include "crypto_test_ec.h"
#include <corecrypto/ccsha1.h>
#include <corecrypto/ccsha2.h>
#include <corecrypto/ccrng_ecfips_test.h>
#include <corecrypto/ccec_priv.h>
#include "ccec_internal.h"
const struct ccecdsa_vector ccecdsa_vectors[]=
{
#include "../test_vectors/ecdsa.inc"
#include "../test_vectors/p256-sha256.inc"
{
.di=NULL,
},
};
// Process one vector
static int ccecdsa_kat_vector(const struct ccecdsa_vector *test)
{
int status = 0; // fail
byteBuffer expected_r = hexStringToBytes(test->r);
byteBuffer expected_s = hexStringToBytes(test->s);
byteBuffer priv_key = hexStringToBytes(test->priv_key);
byteBuffer k = hexStringToBytes(test->k);
byteBuffer x = hexStringToBytes(test->qx);
byteBuffer y = hexStringToBytes(test->qy);
struct ccrng_ecfips_test_state rng;
ccec_const_cp_t cp=test->curve();
const struct ccdigest_info *di=test->di;
ccec_full_ctx_decl_cp(cp, key);
ccec_ctx_init(cp, key);
bool valid;
ccec_pub_ctx_t pkey= ccec_ctx_pub(key);
if (priv_key->len) {
// Generate "remote" public key from private key
ok_or_fail((ccec_recover_full_key(cp,priv_key->len, priv_key->bytes, key) == 0), "Generated Full Key");
} else {
ok_or_fail((ccec_make_pub(ccec_cp_prime_bitlen(cp), x->len, x->bytes,
y->len, y->bytes, pkey)==0), "Generated Pub Key");
}
// Buffer for outputs
byteBuffer computed_r = mallocByteBuffer(ccec_signature_r_s_size(pkey));
byteBuffer computed_s = mallocByteBuffer(ccec_signature_r_s_size(pkey));
byteBuffer hash = mallocByteBuffer(di->output_size);
if(test->hex_msg == 1){
byteBuffer m = hexStringToBytes(test->msg);
ccdigest(di, m->len, m->bytes, hash->bytes);
free(m);
}else{
ccdigest(di, strlen(test->msg), test->msg, hash->bytes);
}
// ccec_print_full_key("Imported key", key);
ok_or_goto((ccec_verify_composite(pkey, di->output_size, hash->bytes,
expected_r->bytes, expected_s->bytes, &valid)==0), "Verify", errout);
ok_or_goto(valid==true, "Stock signature verification", errout);
if (k->len && priv_key->len) {
// Set RNG to control k
ccrng_ecfips_test_init(&rng, k->len, k->bytes);
ok_or_goto((ccec_sign_composite(key, di->output_size, hash->bytes,
computed_r->bytes, computed_s->bytes, (struct ccrng_state *)&rng)==0), "Sign", errout);
ok_or_goto((ccec_verify_composite(pkey, di->output_size, hash->bytes,
computed_r->bytes, computed_s->bytes, &valid)==0), "Verify", errout);
ok_or_goto(valid==true, "Generated signature verification", errout);
// Checks
//cc_print("r: ",expected_r->len, computed_r->bytes);
//cc_print("s: ",expected_s->len, computed_s->bytes);
ok_or_goto(memcmp(computed_r->bytes,expected_r->bytes,expected_r->len)==0, "signature r", errout);
ok_or_goto(memcmp(computed_s->bytes,expected_s->bytes,expected_s->len)==0, "signature s", errout);
}
status = 1; // success
errout:
free(computed_r);
free(computed_s);
free(hash);
free(expected_r);
free(expected_s);
free(priv_key);
free(k);
free(x);
free(y);
return status;
}
// Process one vector
static int ccecdsa_negative_vector(const struct ccecdsa_vector *test)
{
int status = 0; // fail
byteBuffer expected_r = hexStringToBytes(test->r);
byteBuffer expected_s = hexStringToBytes(test->s);
byteBuffer x = hexStringToBytes(test->qx);
byteBuffer y = hexStringToBytes(test->qy);
byteBuffer priv_key = hexStringToBytes(test->priv_key);
byteBuffer k = hexStringToBytes(test->k);
struct ccrng_ecfips_test_state rng;
ccec_const_cp_t cp=test->curve();
const struct ccdigest_info *di=test->di;
ccec_full_ctx_decl_cp(cp, key);
bool valid;
ccec_pub_ctx_t pkey= ccec_ctx_pub(key);
if (priv_key->len) {
// Generate "remote" public key from private key
ok_or_fail((ccec_recover_full_key(cp,priv_key->len, priv_key->bytes, key) == 0), "Generated Full Key");
} else {
ok_or_fail((ccec_make_pub(ccec_cp_prime_bitlen(cp), x->len, x->bytes,
y->len, y->bytes, pkey)==0), "Generated Pub Key");
}
// Buffer for outputs
byteBuffer computed_r = mallocByteBuffer(ccec_signature_r_s_size(pkey));
byteBuffer computed_s = mallocByteBuffer(ccec_signature_r_s_size(pkey));
byteBuffer hash = mallocByteBuffer(di->output_size);
if(test->hex_msg == 1){
byteBuffer m = hexStringToBytes(test->msg);
ccdigest(di, m->len, m->bytes, hash->bytes);
free(m);
}else{
ccdigest(di, strlen(test->msg), test->msg, hash->bytes);
}
//==============================================
// Negative testing of verify
//==============================================
// Good verify
ok_or_goto((ccec_verify_composite(pkey, di->output_size, hash->bytes,
expected_r->bytes, expected_s->bytes, &valid)==0), "Verify", errout);
ok_or_goto(valid==true, "Good signature", errout);
// r is corrupted
expected_r->bytes[0]^=1;
ok_or_goto((ccec_verify_composite(pkey, di->output_size, hash->bytes,
expected_r->bytes, expected_s->bytes, &valid)==0), "Verify: r corrupted", errout);
ok_or_goto(valid==false, "r corrupted", errout);
expected_r->bytes[0]^=1;
// s is corrupted
expected_s->bytes[0]^=1;
ok_or_goto((ccec_verify_composite(pkey, di->output_size, hash->bytes,
expected_r->bytes, expected_s->bytes, &valid)==0), "Verify: s corrupted", errout);
ok_or_goto(valid==false, "s corrupted", errout);
expected_s->bytes[0]^=1;
if (k->len && priv_key->len) {
//==============================================
// Negative testing of signature
//==============================================
// Set RNG to control k
ccrng_ecfips_test_init(&rng, k->len, k->bytes);
ok_or_goto((ccec_sign_composite(key, di->output_size, hash->bytes,
computed_r->bytes, computed_s->bytes, (struct ccrng_state *)&rng)==0), "Sign", errout);
// Checks
ok_or_goto(memcmp(computed_r->bytes,expected_r->bytes,expected_r->len)==0, "signature r", errout);
ok_or_goto(memcmp(computed_s->bytes,expected_s->bytes,expected_s->len)==0, "signature s", errout);
// RNG error
ccrng_ecfips_test_init(&rng, 0, k->bytes);
ok_or_goto((ccec_sign_composite(key, di->output_size, hash->bytes,
computed_r->bytes, computed_s->bytes, (struct ccrng_state *)&rng)!=0), "Sign: rng", errout);
// Private scalar is zero
ccrng_ecfips_test_init(&rng, k->len, k->bytes);
ccn_zero(ccec_cp_n(cp),ccec_ctx_k(key));
ok_or_goto((ccec_sign_composite(key, di->output_size, hash->bytes,
computed_r->bytes, computed_s->bytes, (struct ccrng_state *)&rng)!=0), "Private scalar is zero", errout);
// Private scalar is the order
ccrng_ecfips_test_init(&rng, k->len, k->bytes);
ccn_set(ccec_cp_n(cp),ccec_ctx_k(key),cczp_prime(ccec_cp_zq(cp)));
ok_or_goto((ccec_sign_composite(key, di->output_size, hash->bytes,
computed_r->bytes, computed_s->bytes, (struct ccrng_state *)&rng)!=0), "Private scalar is too big", errout);
}
status = 1; // success
errout:
free(computed_r);
free(computed_s);
free(hash);
free(expected_r);
free(expected_s);
free(priv_key);
free(k);
free(x);
free(y);
return status;
}
int
ecdsa_known_answer_tests(void)
{
size_t test_counter=0;
int test_status=1;
const struct ccecdsa_vector * current_test=&ccecdsa_vectors[test_counter++];
while (current_test->di!=NULL)
{
test_status=ccecdsa_kat_vector(current_test);
current_test=&ccecdsa_vectors[test_counter++];
}
return test_status;
}
int
ecdsa_negative_tests(void)
{
size_t test_counter=0;
int test_status=1;
const struct ccecdsa_vector * current_test=&ccecdsa_vectors[test_counter++];
while (current_test->di!=NULL)
{
test_status=ccecdsa_negative_vector(current_test);
current_test=&ccecdsa_vectors[test_counter++];
}
return test_status;
}