Changeset View
Changeset View
Standalone View
Standalone View
b/tests/fipsdrv.c
Context not available. | |||||
return key; | return key; | ||||
} | } | ||||
/* Generate an ECDSA key on the specified curve and return the complete | |||||
S-expression. */ | |||||
static gcry_sexp_t | |||||
ecdsa_gen_key (const char *curve) | |||||
{ | |||||
gpg_error_t err; | |||||
gcry_sexp_t keyspec, key; | |||||
err = gcry_sexp_build (&keyspec, NULL, | |||||
"(genkey" | |||||
" (ecc" | |||||
" (use-fips186)" | |||||
" (curve %s)))", | |||||
curve); | |||||
if (err) | |||||
die ("gcry_sexp_build failed for ECDSA key generation: %s\n", | |||||
gpg_strerror (err)); | |||||
err = gcry_pk_genkey (&key, keyspec); | |||||
if (err) | |||||
die ("gcry_pk_genkey failed for ECDSA: %s\n", gpg_strerror (err)); | |||||
gcry_sexp_release (keyspec); | |||||
return key; | |||||
} | |||||
/* Print the domain parameter as well as the derive information. KEY | /* Print the domain parameter as well as the derive information. KEY | ||||
is the complete key as returned by dsa_gen. We print to stdout | is the complete key as returned by dsa_gen. We print to stdout | ||||
Context not available. | |||||
} | } | ||||
␌ | |||||
static int | |||||
ecdsa_hash_from_string(const char *algo_string) | |||||
{ | |||||
if (strncmp(algo_string, "SHA-", 4)) | |||||
die("algorithms other than the SHA family are unsupported\n"); | |||||
switch(atoi(algo_string + 4)) | |||||
{ | |||||
case 1: | |||||
return GCRY_MD_SHA1; | |||||
case 224: | |||||
return GCRY_MD_SHA224; | |||||
case 256: | |||||
return GCRY_MD_SHA256; | |||||
case 384: | |||||
return GCRY_MD_SHA384; | |||||
case 512: | |||||
return GCRY_MD_SHA512; | |||||
default: | |||||
die("unsupported SHA function\n"); | |||||
} | |||||
return GCRY_MD_NONE; | |||||
} | |||||
/* Print public key Q (in octet-string format) and private key d. | |||||
KEY is the complete key as returned by ecdsa_gen_key. | |||||
with one parameter per line in hex format using this order: d, Q. */ | |||||
static void | |||||
print_ecdsa_dq (gcry_sexp_t key) | |||||
{ | |||||
gcry_sexp_t l1, l2; | |||||
gcry_mpi_t mpi; | |||||
int idx; | |||||
l1 = gcry_sexp_find_token (key, "private-key", 0); | |||||
if (!l1) | |||||
die ("private key not found in genkey result\n"); | |||||
l2 = gcry_sexp_find_token (l1, "ecc", 0); | |||||
if (!l2) | |||||
die ("returned private key not formed as expected\n"); | |||||
gcry_sexp_release (l1); | |||||
l1 = l2; | |||||
/* Extract the parameters from the S-expression and print them to stdout. */ | |||||
for (idx=0; "dq"[idx]; idx++) | |||||
{ | |||||
l2 = gcry_sexp_find_token (l1, "dq"+idx, 1); | |||||
if (!l2) | |||||
die ("no %c parameter in returned public key\n", "dq"[idx]); | |||||
mpi = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); | |||||
if (!mpi) | |||||
die ("no value for %c parameter in returned private key\n","dq"[idx]); | |||||
gcry_sexp_release (l2); | |||||
if (standalone_mode) | |||||
printf ("%c = ", "dQ"[idx]); | |||||
print_mpi_line (mpi, 1); | |||||
gcry_mpi_release (mpi); | |||||
} | |||||
gcry_sexp_release (l1); | |||||
} | |||||
/* Generate an ECDSA key with specified domain parameters | |||||
and print the d and Q values, in the standard octet-string format. */ | |||||
static void | |||||
run_ecdsa_gen_key (const char *curve) | |||||
{ | |||||
gcry_sexp_t key; | |||||
key = ecdsa_gen_key (curve); | |||||
print_ecdsa_dq (key); | |||||
gcry_sexp_release (key); | |||||
} | |||||
␌ | |||||
/* Sign DATA of length DATALEN using the key taken from the S-expression | |||||
encoded KEYFILE. */ | |||||
static void | |||||
run_ecdsa_sign (const void *data, size_t datalen, const char *keyfile, const char *algo_string) | |||||
{ | |||||
gpg_error_t err; | |||||
gcry_sexp_t s_data, s_key, s_sig, s_tmp, s_tmp2; | |||||
char hash[128]; | |||||
gcry_mpi_t tmpmpi; | |||||
int algo; | |||||
s_key = read_sexp_from_file (keyfile); | |||||
algo = ecdsa_hash_from_string (algo_string); | |||||
gcry_md_hash_buffer (algo, hash, data, datalen); | |||||
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, | |||||
gcry_md_get_algo_dlen(algo), NULL); | |||||
if (!err) | |||||
{ | |||||
err = gcry_sexp_build (&s_data, NULL, | |||||
"(data (flags raw)(value %m))", tmpmpi); | |||||
gcry_mpi_release (tmpmpi); | |||||
} | |||||
if (err) | |||||
die ("gcry_sexp_build failed for ECDSA data input: %s\n", | |||||
gpg_strerror (err)); | |||||
gcry_sexp_release (s_data); | |||||
gcry_sexp_release (s_key); | |||||
/* Now return the actual signature. */ | |||||
s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); | |||||
if (!s_tmp) | |||||
die ("no sig-val element in returned S-expression\n"); | |||||
gcry_sexp_release (s_sig); | |||||
s_sig = s_tmp; | |||||
s_tmp = gcry_sexp_find_token (s_sig, "ecdsa", 0); | |||||
if (!s_tmp) | |||||
die ("no ecdsa element in returned S-expression\n"); | |||||
gcry_sexp_release (s_sig); | |||||
s_sig = s_tmp; | |||||
s_tmp = gcry_sexp_find_token (s_sig, "r", 0); | |||||
tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG); | |||||
if (!tmpmpi) | |||||
die ("no r parameter in returned S-expression\n"); | |||||
print_mpi_line (tmpmpi, 1); | |||||
gcry_mpi_release (tmpmpi); | |||||
gcry_sexp_release (s_tmp); | |||||
s_tmp = gcry_sexp_find_token (s_sig, "s", 0); | |||||
tmpmpi = gcry_sexp_nth_mpi (s_tmp, 1, GCRYMPI_FMT_USG); | |||||
if (!tmpmpi) | |||||
die ("no s parameter in returned S-expression\n"); | |||||
print_mpi_line (tmpmpi, 1); | |||||
gcry_mpi_release (tmpmpi); | |||||
gcry_sexp_release (s_tmp); | |||||
gcry_sexp_release (s_sig); | |||||
} | |||||
␌ | |||||
/* Verify DATA of length DATALEN using the public key taken from the | |||||
S-expression in KEYFILE against the S-expression formatted | |||||
signature in SIGFILE. */ | |||||
static void | |||||
run_ecdsa_verify (const void *data, size_t datalen, | |||||
const char *keyfile, const char *algo_string, const char *sigfile) | |||||
{ | |||||
gpg_error_t err; | |||||
gcry_sexp_t s_data, s_key, s_sig; | |||||
char hash[128]; | |||||
gcry_mpi_t tmpmpi; | |||||
int algo; | |||||
s_key = read_sexp_from_file (keyfile); | |||||
algo = ecdsa_hash_from_string(algo_string); | |||||
gcry_md_hash_buffer (algo, hash, data, datalen); | |||||
/* Note that we can't simply use %b with HASH to build the | |||||
S-expression, because that might yield a negative value. */ | |||||
err = gcry_mpi_scan (&tmpmpi, GCRYMPI_FMT_USG, hash, | |||||
gcry_md_get_algo_dlen(algo), NULL); | |||||
if (!err) | |||||
{ | |||||
err = gcry_sexp_build (&s_data, NULL, | |||||
"(data (flags raw)(value %m))", tmpmpi); | |||||
gcry_mpi_release (tmpmpi); | |||||
} | |||||
if (err) | |||||
die ("gcry_sexp_build failed for DSA data input: %s\n", | |||||
gpg_strerror (err)); | |||||
s_sig = read_sexp_from_file (sigfile); | |||||
err = gcry_pk_verify (s_sig, s_data, s_key); | |||||
if (!err) | |||||
puts ("GOOD signature"); | |||||
else if (gpg_err_code (err) == GPG_ERR_BAD_SIGNATURE) | |||||
puts ("BAD signature"); | |||||
else | |||||
printf ("ERROR (%s)\n", gpg_strerror (err)); | |||||
gcry_sexp_release (s_sig); | |||||
gcry_sexp_release (s_key); | |||||
gcry_sexp_release (s_data); | |||||
} | |||||
␌ | ␌ | ||||
static void | static void | ||||
Context not available. | |||||
"Run a crypto operation using hex encoded input and output.\n" | "Run a crypto operation using hex encoded input and output.\n" | ||||
"MODE:\n" | "MODE:\n" | ||||
" encrypt, decrypt, digest, random, hmac-sha,\n" | " encrypt, decrypt, digest, random, hmac-sha,\n" | ||||
" rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}\n" | " rsa-{derive,gen,sign,verify}, dsa-{pqg-gen,gen,sign,verify}, ecdsa-{gen-key,sign,verify}\n" | ||||
"OPTIONS:\n" | "OPTIONS:\n" | ||||
" --verbose Print additional information\n" | " --verbose Print additional information\n" | ||||
" --binary Input and output is in binary form\n" | " --binary Input and output is in binary form\n" | ||||
Context not available. | |||||
" --iv IV Use the hex encoded IV\n" | " --iv IV Use the hex encoded IV\n" | ||||
" --dt DT Use the hex encoded DT for the RNG\n" | " --dt DT Use the hex encoded DT for the RNG\n" | ||||
" --algo NAME Use algorithm NAME\n" | " --algo NAME Use algorithm NAME\n" | ||||
" --curve NAME Select ECC curve spec NAME\n" | |||||
" --keysize N Use a keysize of N bits\n" | " --keysize N Use a keysize of N bits\n" | ||||
" --signature NAME Take signature from file NAME\n" | " --signature NAME Take signature from file NAME\n" | ||||
" --chunk N Read in chunks of N bytes (implies --binary)\n" | " --chunk N Read in chunks of N bytes (implies --binary)\n" | ||||
Context not available. | |||||
int progress = 0; | int progress = 0; | ||||
int use_pkcs1 = 0; | int use_pkcs1 = 0; | ||||
const char *mode_string; | const char *mode_string; | ||||
const char *curve_string = NULL; | |||||
const char *key_string = NULL; | const char *key_string = NULL; | ||||
const char *iv_string = NULL; | const char *iv_string = NULL; | ||||
const char *dt_string = NULL; | const char *dt_string = NULL; | ||||
Context not available. | |||||
binary_input = binary_output = 1; | binary_input = binary_output = 1; | ||||
argc--; argv++; | argc--; argv++; | ||||
} | } | ||||
else if (!strcmp (*argv, "--curve")) | |||||
{ | |||||
argc--; argv++; | |||||
if (!argc) | |||||
usage (0); | |||||
curve_string = *argv; | |||||
argc--; argv++; | |||||
} | |||||
else if (!strcmp (*argv, "--pkcs1")) | else if (!strcmp (*argv, "--pkcs1")) | ||||
{ | { | ||||
use_pkcs1 = 1; | use_pkcs1 = 1; | ||||
Context not available. | |||||
&& !mct_server | && !mct_server | ||||
&& strcmp (mode_string, "random") | && strcmp (mode_string, "random") | ||||
&& strcmp (mode_string, "rsa-gen") | && strcmp (mode_string, "rsa-gen") | ||||
&& strcmp (mode_string, "dsa-gen") ) | && strcmp (mode_string, "dsa-gen") | ||||
&& strcmp (mode_string, "ecdsa-gen-key") ) | |||||
{ | { | ||||
data = read_file (input, !binary_input, &datalen); | data = read_file (input, !binary_input, &datalen); | ||||
if (!data) | if (!data) | ||||
Context not available. | |||||
run_dsa_verify (data, datalen, key_string, signature_string); | run_dsa_verify (data, datalen, key_string, signature_string); | ||||
} | } | ||||
else if (!strcmp (mode_string, "ecdsa-gen-key")) | |||||
{ | |||||
if (!curve_string) | |||||
die ("option --curve containing name of the specified curve is required in this mode\n"); | |||||
run_ecdsa_gen_key (curve_string); | |||||
} | |||||
else if (!strcmp (mode_string, "ecdsa-sign")) | |||||
{ | |||||
if (!key_string) | |||||
die ("option --key is required in this mode\n"); | |||||
if (access (key_string, R_OK)) | |||||
die ("option --key needs to specify an existing keyfile\n"); | |||||
if (!algo_string) | |||||
die ("use --algo to specify the hash algorithm\n"); | |||||
if (!data) | |||||
die ("no data available (do not use --chunk)\n"); | |||||
run_ecdsa_sign (data, datalen, key_string, algo_string); | |||||
} | |||||
else if (!strcmp (mode_string, "ecdsa-verify")) | |||||
{ | |||||
if (!key_string) | |||||
die ("option --key is required in this mode\n"); | |||||
if (access (key_string, R_OK)) | |||||
die ("option --key needs to specify an existing keyfile\n"); | |||||
if (!algo_string) | |||||
die ("use --algo to specify the hash algorithm\n"); | |||||
if (!data) | |||||
die ("no data available (do not use --chunk)\n"); | |||||
if (!signature_string) | |||||
die ("option --signature is required in this mode\n"); | |||||
if (access (signature_string, R_OK)) | |||||
die ("option --signature needs to specify an existing file\n"); | |||||
run_ecdsa_verify (data, datalen, key_string, algo_string, signature_string); | |||||
} | |||||
else | else | ||||
usage (0); | usage (0); | ||||
Context not available. |