diff --git a/cipher/pubkey.c b/cipher/pubkey.c index f19d5f66..2d80ee08 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -1,1241 +1,1241 @@ /* pubkey.c - pubkey dispatcher * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, * 2007, 2008, 2011 Free Software Foundation, Inc. * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #include #include #include #include #include #include "g10lib.h" #include "mpi.h" #include "cipher.h" #include "context.h" #include "pubkey-internal.h" /* This is the list of the public-key algorithms included in Libgcrypt. */ static gcry_pk_spec_t * const pubkey_list[] = { #if USE_ECC &_gcry_pubkey_spec_ecc, #endif #if USE_RSA &_gcry_pubkey_spec_rsa, #endif #if USE_DSA &_gcry_pubkey_spec_dsa, #endif #if USE_ELGAMAL &_gcry_pubkey_spec_elg, #endif NULL }; static int map_algo (int algo) { switch (algo) { case GCRY_PK_RSA_E: return GCRY_PK_RSA; case GCRY_PK_RSA_S: return GCRY_PK_RSA; case GCRY_PK_ELG_E: return GCRY_PK_ELG; case GCRY_PK_ECDSA: return GCRY_PK_ECC; case GCRY_PK_EDDSA: return GCRY_PK_ECC; case GCRY_PK_ECDH: return GCRY_PK_ECC; default: return algo; } } /* Return the spec structure for the public key algorithm ALGO. For an unknown algorithm NULL is returned. */ static gcry_pk_spec_t * spec_from_algo (int algo) { int idx; gcry_pk_spec_t *spec; algo = map_algo (algo); for (idx = 0; (spec = pubkey_list[idx]); idx++) if (algo == spec->algo) return spec; return NULL; } /* Return the spec structure for the public key algorithm with NAME. For an unknown name NULL is returned. */ static gcry_pk_spec_t * spec_from_name (const char *name) { gcry_pk_spec_t *spec; int idx; const char **aliases; for (idx=0; (spec = pubkey_list[idx]); idx++) { if (!stricmp (name, spec->name)) return spec; for (aliases = spec->aliases; *aliases; aliases++) if (!stricmp (name, *aliases)) return spec; } return NULL; } /* Given the s-expression SEXP with the first element be either * "private-key" or "public-key" return the spec structure for it. We * look through the list to find a list beginning with "private-key" * or "public-key" - the first one found is used. If WANT_PRIVATE is * set the function will only succeed if a private key has been given. * On success the spec is stored at R_SPEC. On error NULL is stored * at R_SPEC and an error code returned. If R_PARMS is not NULL and * the function returns success, the parameter list below * "private-key" or "public-key" is stored there and the caller must * call gcry_sexp_release on it. */ static gcry_err_code_t spec_from_sexp (gcry_sexp_t sexp, int want_private, gcry_pk_spec_t **r_spec, gcry_sexp_t *r_parms) { gcry_sexp_t list, l2; char *name; gcry_pk_spec_t *spec; *r_spec = NULL; if (r_parms) *r_parms = NULL; /* Check that the first element is valid. If we are looking for a public key but a private key was supplied, we allow the use of the private key anyway. The rationale for this is that the private key is a superset of the public key. */ list = sexp_find_token (sexp, want_private? "private-key":"public-key", 0); if (!list && !want_private) list = sexp_find_token (sexp, "private-key", 0); if (!list) return GPG_ERR_INV_OBJ; /* Does not contain a key object. */ l2 = sexp_cadr (list); sexp_release (list); list = l2; name = sexp_nth_string (list, 0); if (!name) { sexp_release ( list ); return GPG_ERR_INV_OBJ; /* Invalid structure of object. */ } spec = spec_from_name (name); xfree (name); if (!spec) { sexp_release (list); return GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ } *r_spec = spec; if (r_parms) *r_parms = list; else sexp_release (list); return 0; } /* Disable the use of the algorithm ALGO. This is not thread safe and should thus be called early. */ static void disable_pubkey_algo (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); if (spec) spec->flags.disabled = 1; } /* * Map a string to the pubkey algo */ int _gcry_pk_map_name (const char *string) { gcry_pk_spec_t *spec; if (!string) return 0; spec = spec_from_name (string); if (!spec) return 0; if (spec->flags.disabled) return 0; return spec->algo; } /* Map the public key algorithm whose ID is contained in ALGORITHM to a string representation of the algorithm name. For unknown algorithm IDs this functions returns "?". */ const char * _gcry_pk_algo_name (int algo) { gcry_pk_spec_t *spec; spec = spec_from_algo (algo); if (spec) return spec->name; return "?"; } /**************** * A USE of 0 means: don't care. */ static gcry_err_code_t check_pubkey_algo (int algo, unsigned use) { gcry_err_code_t err = 0; gcry_pk_spec_t *spec; spec = spec_from_algo (algo); if (spec && !spec->flags.disabled) { if (((use & GCRY_PK_USAGE_SIGN) && (! (spec->use & GCRY_PK_USAGE_SIGN))) || ((use & GCRY_PK_USAGE_ENCR) && (! (spec->use & GCRY_PK_USAGE_ENCR)))) err = GPG_ERR_WRONG_PUBKEY_ALGO; } else err = GPG_ERR_PUBKEY_ALGO; return err; } /**************** * Return the number of public key material numbers */ static int pubkey_get_npkey (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_pkey) : 0; } /**************** * Return the number of secret key material numbers */ static int pubkey_get_nskey (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_skey) : 0; } /**************** * Return the number of signature material numbers */ static int pubkey_get_nsig (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_sig) : 0; } /**************** * Return the number of encryption material numbers */ static int pubkey_get_nenc (int algo) { gcry_pk_spec_t *spec = spec_from_algo (algo); return spec? strlen (spec->elements_enc) : 0; } /* Do a PK encrypt operation Caller has to provide a public key as the SEXP pkey and data as a SEXP with just one MPI in it. Alternatively S_DATA might be a complex S-Expression, similar to the one used for signature verification. This provides a flag which allows to handle PKCS#1 block type 2 padding. The function returns a sexp which may be passed to to pk_decrypt. Returns: 0 or an errorcode. s_data = See comment for _gcry_pk_util_data_to_mpi s_pkey = r_ciph = (enc-val ( ( ) ... ( ) )) */ gcry_err_code_t _gcry_pk_encrypt (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t s_pkey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_ciph = NULL; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) rc = GPG_ERR_CIPHER_ALGO; else if (spec->encrypt) rc = spec->encrypt (r_ciph, s_data, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } /* Do a PK decrypt operation Caller has to provide a secret key as the SEXP skey and data in a format as created by gcry_pk_encrypt. For historic reasons the function returns simply an MPI as an S-expression part; this is deprecated and the new method should be used which returns a real S-expressionl this is selected by adding at least an empty flags list to S_DATA. Returns: 0 or an errorcode. s_data = (enc-val [(flags [raw, pkcs1, oaep])] ( ( ) ... ( ) )) s_skey = r_plain= Either an incomplete S-expression without the parentheses or if the flags list is used (even if empty) a real S-expression: (value PLAIN). In raw mode (or no flags given) the returned value is to be interpreted as a signed MPI, thus it may have an extra leading zero octet even if not included in the original data. With pkcs1 or oaep decoding enabled the returned value is a verbatim octet string. */ gcry_err_code_t _gcry_pk_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t s_skey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_plain = NULL; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) rc = GPG_ERR_CIPHER_ALGO; else if (spec->decrypt) rc = spec->decrypt (r_plain, s_data, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } /* Create a signature. Caller has to provide a secret key as the SEXP skey and data expressed as a SEXP list hash with only one element which should instantly be available as a MPI. Alternatively the structure given below may be used for S_HASH, it provides the abiliy to pass flags to the operation; the flags defined by now are "pkcs1" which does PKCS#1 block type 1 style padding and "pss" for PSS encoding. Returns: 0 or an errorcode. In case of 0 the function returns a new SEXP with the signature value; the structure of this signature depends on the other arguments but is always suitable to be passed to gcry_pk_verify s_hash = See comment for _gcry-pk_util_data_to_mpi s_skey = r_sig = (sig-val ( ( ) ... ( )) [(hash algo)]) Note that (hash algo) in R_SIG is not used. */ gcry_err_code_t _gcry_pk_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_hash, gcry_sexp_t s_skey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; *r_sig = NULL; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) rc = GPG_ERR_CIPHER_ALGO; else if (spec->sign) rc = spec->sign (r_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } gcry_err_code_t _gcry_pk_sign_md (gcry_sexp_t *r_sig, const char *tmpl, gcry_md_hd_t hd_orig, gcry_sexp_t s_skey, gcry_ctx_t ctx) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms = NULL; gcry_sexp_t s_hash = NULL; int algo; const unsigned char *digest; gcry_error_t err; gcry_md_hd_t hd; char *s; char *hash_name; *r_sig = NULL; /* Check if it has fixed hash name or %s */ s = strstr (tmpl, "(hash "); if (s == NULL) return GPG_ERR_DIGEST_ALGO; s += 6; if (!strncmp (s, "%s", 2)) hash_name = NULL; else { char *p; for (p = s; *p && *p != ' '; p++) ; hash_name = xtrymalloc (p - s + 1); if (!hash_name) return gpg_error_from_syserror (); memcpy (hash_name, s, p - s); hash_name[p - s] = 0; } err = _gcry_md_copy (&hd, hd_orig); if (err) { xfree (hash_name); return gpg_err_code (err); } if (hash_name) { algo = _gcry_md_map_name (hash_name); if (algo == 0 || (fips_mode () && algo == GCRY_MD_SHA1)) { xfree (hash_name); _gcry_md_close (hd); return GPG_ERR_DIGEST_ALGO; } digest = _gcry_md_read (hd, algo); } else { algo = _gcry_md_get_algo (hd); if (fips_mode () && algo == GCRY_MD_SHA1) return GPG_ERR_DIGEST_ALGO; digest = _gcry_md_read (hd, 0); } if (!digest) { xfree (hash_name); _gcry_md_close (hd); return GPG_ERR_NOT_IMPLEMENTED; } if (!ctx) { if (hash_name) rc = _gcry_sexp_build (&s_hash, NULL, tmpl, (int) _gcry_md_get_algo_dlen (algo), digest); else rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest); } else { const unsigned char *p; size_t len; rc = _gcry_pk_get_random_override (ctx, &p, &len); if (rc) { _gcry_md_close (hd); return rc; } if (hash_name) rc = _gcry_sexp_build (&s_hash, NULL, tmpl, (int) _gcry_md_get_algo_dlen (algo), digest, (int) len, p); else rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest, (int) len, p); } xfree (hash_name); _gcry_md_close (hd); if (rc) return rc; rc = spec_from_sexp (s_skey, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) rc = GPG_ERR_CIPHER_ALGO; else if (spec->sign) rc = spec->sign (r_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (s_hash); sexp_release (keyparms); return rc; } /* Verify a signature. Caller has to supply the public key pkey, the signature sig and his hashvalue data. Public key has to be a standard public key given as an S-Exp, sig is a S-Exp as returned from gcry_pk_sign and data must be an S-Exp like the one in sign too. */ gcry_err_code_t _gcry_pk_verify (gcry_sexp_t s_sig, gcry_sexp_t s_hash, gcry_sexp_t s_pkey) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) rc = GPG_ERR_CIPHER_ALGO; else if (spec->verify) rc = spec->verify (s_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } gcry_err_code_t _gcry_pk_verify_md (gcry_sexp_t s_sig, const char *tmpl, gcry_md_hd_t hd_orig, gcry_sexp_t s_pkey, gcry_ctx_t ctx) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms = NULL; gcry_sexp_t s_hash = NULL; int algo; const unsigned char *digest; gcry_error_t err; gcry_md_hd_t hd; err = _gcry_md_copy (&hd, hd_orig); if (err) return gpg_err_code (err); algo = _gcry_md_get_algo (hd); if (fips_mode () && algo == GCRY_MD_SHA1) return GPG_ERR_DIGEST_ALGO; digest = _gcry_md_read (hd, 0); if (!digest) { _gcry_md_close (hd); return GPG_ERR_DIGEST_ALGO; } if (!ctx) rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest); else { const unsigned char *p; size_t len; rc = _gcry_pk_get_random_override (ctx, &p, &len); if (rc) { _gcry_md_close (hd); return rc; } rc = _gcry_sexp_build (&s_hash, NULL, tmpl, _gcry_md_algo_name (algo), (int) _gcry_md_get_algo_dlen (algo), digest, (int) len, p); } _gcry_md_close (hd); if (rc) return rc; rc = spec_from_sexp (s_pkey, 0, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) rc = GPG_ERR_CIPHER_ALGO; else if (spec->verify) rc = spec->verify (s_sig, s_hash, keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (s_hash); sexp_release (keyparms); return rc; } /* Test a key. This may be used either for a public or a secret key to see whether the internal structure is okay. Returns: 0 or an errorcode. NOTE: We currently support only secret key checking. */ gcry_err_code_t _gcry_pk_testkey (gcry_sexp_t s_key) { gcry_err_code_t rc; gcry_pk_spec_t *spec; gcry_sexp_t keyparms; rc = spec_from_sexp (s_key, 1, &spec, &keyparms); if (rc) goto leave; if (spec->flags.disabled) rc = GPG_ERR_CIPHER_ALGO; else if (spec->check_secret_key) rc = spec->check_secret_key (keyparms); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (keyparms); return rc; } /* Create a public key pair and return it in r_key. How the key is created depends on s_parms: (genkey (algo (parameter_name_1 ....) .... (parameter_name_n ....) )) The key is returned in a format depending on the algorithm. Both, private and secret keys are returned and optionally some additional informatin. For elgamal we return this structure: (key-data (public-key (elg (p ) (g ) (y ) ) ) (private-key (elg (p ) (g ) (y ) (x ) ) ) (misc-key-info (pm1-factors n1 n2 ... nn) )) */ gcry_err_code_t _gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) { gcry_pk_spec_t *spec = NULL; gcry_sexp_t list = NULL; gcry_sexp_t l2 = NULL; char *name = NULL; gcry_err_code_t rc; *r_key = NULL; list = sexp_find_token (s_parms, "genkey", 0); if (!list) { rc = GPG_ERR_INV_OBJ; /* Does not contain genkey data. */ goto leave; } l2 = sexp_cadr (list); sexp_release (list); list = l2; l2 = NULL; if (! list) { rc = GPG_ERR_NO_OBJ; /* No cdr for the genkey. */ goto leave; } name = _gcry_sexp_nth_string (list, 0); if (!name) { rc = GPG_ERR_INV_OBJ; /* Algo string missing. */ goto leave; } spec = spec_from_name (name); xfree (name); name = NULL; - if (!spec) + if (!spec || spec->flags.disabled) { rc = GPG_ERR_PUBKEY_ALGO; /* Unknown algorithm. */ goto leave; } if (spec->generate) rc = spec->generate (list, r_key); else rc = GPG_ERR_NOT_IMPLEMENTED; leave: sexp_release (list); xfree (name); sexp_release (l2); return rc; } /* Get the number of nbits from the public key. Hmmm: Should we have really this function or is it better to have a more general function to retrieve different properties of the key? */ unsigned int _gcry_pk_get_nbits (gcry_sexp_t key) { gcry_pk_spec_t *spec; gcry_sexp_t parms; unsigned int nbits; /* Parsing KEY might be considered too much overhead. For example for RSA we would only need to look at P and stop parsing right away. However, with ECC things are more complicate in that only a curve name might be specified. Thus we need to tear the sexp apart. */ if (spec_from_sexp (key, 0, &spec, &parms)) return 0; /* Error - 0 is a suitable indication for that. */ if (spec->flags.disabled) return 0; nbits = spec->get_nbits (parms); sexp_release (parms); return nbits; } /* Return the so called KEYGRIP which is the SHA-1 hash of the public key parameters expressed in a way depending on the algorithm. ARRAY must either be 20 bytes long or NULL; in the latter case a newly allocated array of that size is returned, otherwise ARRAY or NULL is returned to indicate an error which is most likely an unknown algorithm. The function accepts public or secret keys. */ unsigned char * _gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array) { gcry_sexp_t list = NULL; gcry_sexp_t l2 = NULL; gcry_pk_spec_t *spec = NULL; const char *s; char *name = NULL; int idx; const char *elems; gcry_md_hd_t md = NULL; int okay = 0; /* Check that the first element is valid. */ list = sexp_find_token (key, "public-key", 0); if (! list) list = sexp_find_token (key, "private-key", 0); if (! list) list = sexp_find_token (key, "protected-private-key", 0); if (! list) list = sexp_find_token (key, "shadowed-private-key", 0); if (! list) return NULL; /* No public- or private-key object. */ l2 = sexp_cadr (list); sexp_release (list); list = l2; l2 = NULL; name = _gcry_sexp_nth_string (list, 0); if (!name) goto fail; /* Invalid structure of object. */ spec = spec_from_name (name); if (!spec) goto fail; /* Unknown algorithm. */ elems = spec->elements_grip; if (!elems) goto fail; /* No grip parameter. */ if (_gcry_md_open (&md, GCRY_MD_SHA1, 0)) goto fail; if (spec->comp_keygrip) { /* Module specific method to compute a keygrip. */ if (spec->comp_keygrip (md, list)) goto fail; } else { /* Generic method to compute a keygrip. */ for (idx = 0, s = elems; *s; s++, idx++) { const char *data; size_t datalen; char buf[30]; l2 = sexp_find_token (list, s, 1); if (! l2) goto fail; data = sexp_nth_data (l2, 1, &datalen); if (! data) goto fail; snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen); _gcry_md_write (md, buf, strlen (buf)); _gcry_md_write (md, data, datalen); sexp_release (l2); l2 = NULL; _gcry_md_write (md, ")", 1); } } if (!array) { array = xtrymalloc (20); if (! array) goto fail; } memcpy (array, _gcry_md_read (md, GCRY_MD_SHA1), 20); okay = 1; fail: xfree (name); sexp_release (l2); _gcry_md_close (md); sexp_release (list); return okay? array : NULL; } const char * _gcry_pk_get_curve (gcry_sexp_t key, int iterator, unsigned int *r_nbits) { const char *result = NULL; gcry_pk_spec_t *spec; gcry_sexp_t keyparms = NULL; if (r_nbits) *r_nbits = 0; if (key) { iterator = 0; if (spec_from_sexp (key, 0, &spec, &keyparms)) return NULL; } else { spec = spec_from_name ("ecc"); if (!spec) return NULL; } if (spec->flags.disabled) return NULL; if (spec->get_curve) result = spec->get_curve (keyparms, iterator, r_nbits); sexp_release (keyparms); return result; } gcry_sexp_t _gcry_pk_get_param (int algo, const char *name) { gcry_sexp_t result = NULL; gcry_pk_spec_t *spec = NULL; algo = map_algo (algo); if (algo != GCRY_PK_ECC) return NULL; spec = spec_from_name ("ecc"); if (spec) { if (spec && spec->get_curve_param) result = spec->get_curve_param (name); } return result; } gcry_err_code_t _gcry_pk_ctl (int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc = 0; switch (cmd) { case GCRYCTL_DISABLE_ALGO: /* This one expects a buffer pointing to an integer with the algo number. */ if ((! buffer) || (buflen != sizeof (int))) rc = GPG_ERR_INV_ARG; else disable_pubkey_algo (*((int *) buffer)); break; default: rc = GPG_ERR_INV_OP; } return rc; } /* Return information about the given algorithm WHAT selects the kind of information returned: GCRYCTL_TEST_ALGO: Returns 0 when the specified algorithm is available for use. Buffer must be NULL, nbytes may have the address of a variable with the required usage of the algorithm. It may be 0 for don't care or a combination of the GCRY_PK_USAGE_xxx flags; GCRYCTL_GET_ALGO_USAGE: Return the usage flags for the given algo. An invalid algo returns 0. Disabled algos are ignored here because we only want to know whether the algo is at all capable of the usage. Note: Because this function is in most cases used to return an integer value, we can make it easier for the caller to just look at the return value. The caller will in all cases consult the value and thereby detecting whether a error occurred or not (i.e. while checking the block size) */ gcry_err_code_t _gcry_pk_algo_info (int algorithm, int what, void *buffer, size_t *nbytes) { gcry_err_code_t rc = 0; switch (what) { case GCRYCTL_TEST_ALGO: { int use = nbytes ? *nbytes : 0; if (buffer) rc = GPG_ERR_INV_ARG; else if (check_pubkey_algo (algorithm, use)) rc = GPG_ERR_PUBKEY_ALGO; break; } case GCRYCTL_GET_ALGO_USAGE: { gcry_pk_spec_t *spec; spec = spec_from_algo (algorithm); *nbytes = spec? spec->use : 0; break; } case GCRYCTL_GET_ALGO_NPKEY: { /* FIXME? */ int npkey = pubkey_get_npkey (algorithm); *nbytes = npkey; break; } case GCRYCTL_GET_ALGO_NSKEY: { /* FIXME? */ int nskey = pubkey_get_nskey (algorithm); *nbytes = nskey; break; } case GCRYCTL_GET_ALGO_NSIGN: { /* FIXME? */ int nsign = pubkey_get_nsig (algorithm); *nbytes = nsign; break; } case GCRYCTL_GET_ALGO_NENCR: { /* FIXME? */ int nencr = pubkey_get_nenc (algorithm); *nbytes = nencr; break; } default: rc = GPG_ERR_INV_OP; } return rc; } /* Return an S-expression representing the context CTX. Depending on the state of that context, the S-expression may either be a public key, a private key or any other object used with public key operations. On success a new S-expression is stored at R_SEXP and 0 is returned, on error NULL is store there and an error code is returned. MODE is either 0 or one of the GCRY_PK_GET_xxx values. As of now it only support certain ECC operations because a context object is right now only defined for ECC. Over time this function will be extended to cover more algorithms. Note also that the name of the function is gcry_pubkey_xxx and not gcry_pk_xxx. The idea is that we will eventually provide variants of the existing gcry_pk_xxx functions which will take a context parameter. */ gcry_err_code_t _gcry_pubkey_get_sexp (gcry_sexp_t *r_sexp, int mode, gcry_ctx_t ctx) { mpi_ec_t ec; if (!r_sexp) return GPG_ERR_INV_VALUE; *r_sexp = NULL; switch (mode) { case 0: case GCRY_PK_GET_PUBKEY: case GCRY_PK_GET_SECKEY: break; default: return GPG_ERR_INV_VALUE; } if (!ctx) return GPG_ERR_NO_CRYPT_CTX; ec = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_EC); if (ec) return _gcry_pk_ecc_get_sexp (r_sexp, mode, ec); return GPG_ERR_WRONG_CRYPT_CTX; } /* Explicitly initialize this module. */ gcry_err_code_t _gcry_pk_init (void) { if (fips_mode()) { /* disable algorithms that are disallowed in fips */ int idx; gcry_pk_spec_t *spec; for (idx = 0; (spec = pubkey_list[idx]); idx++) if (!spec->flags.fips) spec->flags.disabled = 1; } return 0; } /* Run the selftests for pubkey algorithm ALGO with optional reporting function REPORT. */ gpg_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec; gcry_pk_spec_t *spec; algo = map_algo (algo); spec = spec_from_algo (algo); if (spec && !spec->flags.disabled && spec->selftest) ec = spec->selftest (algo, extended, report); else { ec = GPG_ERR_PUBKEY_ALGO; /* Fixme: We need to change the report function to allow passing of an encryption mode (e.g. pkcs1, ecdsa, or ecdh). */ if (report) report ("pubkey", algo, "module", spec && !spec->flags.disabled? "no selftest available" : spec? "algorithm disabled" : "algorithm not found"); } return gpg_error (ec); } struct pk_random_override { size_t len; unsigned char area[]; }; gpg_err_code_t _gcry_pk_random_override_new (gcry_ctx_t *r_ctx, const unsigned char *p, size_t len) { gcry_ctx_t ctx; struct pk_random_override *pro; *r_ctx = NULL; if (!p) return GPG_ERR_EINVAL; ctx = _gcry_ctx_alloc (CONTEXT_TYPE_RANDOM_OVERRIDE, sizeof (size_t) + len, NULL); if (!ctx) return gpg_err_code_from_syserror (); pro = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_RANDOM_OVERRIDE); pro->len = len; memcpy (pro->area, p, len); *r_ctx = ctx; return 0; } gpg_err_code_t _gcry_pk_get_random_override (gcry_ctx_t ctx, const unsigned char **r_p, size_t *r_len) { struct pk_random_override *pro; pro = _gcry_ctx_find_pointer (ctx, CONTEXT_TYPE_RANDOM_OVERRIDE); if (!pro) return GPG_ERR_EINVAL; *r_p = pro->area; *r_len = pro->len; return 0; } diff --git a/tests/benchmark.c b/tests/benchmark.c index b35b996c..a45fc5ff 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -1,2056 +1,2063 @@ /* benchmark.c - for libgcrypt * Copyright (C) 2002, 2004, 2005, 2006, 2008 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #ifdef _GCRYPT_IN_LIBGCRYPT # include "../src/gcrypt-int.h" # include "../compat/libcompat.h" #else # include #endif #include "stopwatch.h" #define PGM "benchmark" #include "t-common.h" /* Do encryption tests with large buffers (100 KiB). */ static int large_buffers; /* Do encryption tests with huge buffers (256 MiB). */ static int huge_buffers; /* Number of cipher repetitions. */ static int cipher_repetitions; /* Number of hash repetitions. */ static int hash_repetitions; /* Number of hash repetitions. */ static int mac_repetitions; /* Alignment of the buffers. */ static int buffer_alignment; /* Whether to include the keysetup in the cipher timings. */ static int cipher_with_keysetup; /* Whether fips mode was active at startup. */ static int in_fips_mode; /* Whether we are running as part of the regression test suite. */ static int in_regression_test; /* Whether --progress is in use. */ static int with_progress; /* Runtime flag to switch to a different progress output. */ static int single_char_progress; static const char sample_private_dsa_key_1024[] = "(private-key\n" " (dsa\n" " (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685" "03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A" "853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF" "C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n" " (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n" " (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622" "B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312" "FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3" "85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n" " (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4" "ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6" "66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155" "D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n" " (x #4186F8A58C5DF46C5BCFC7006BEEBF05E93C0CA7#)\n" "))\n"; static const char sample_public_dsa_key_1024[] = "(public-key\n" " (dsa\n" " (p #00A126202D592214C5A8F6016E2C3F4256052ACB1CB17D88E64B1293FAF08F5E4685" "03E6F68366B326A56284370EB2103E92D8346A163E44A08FDC422AC8E9E44268557A" "853539A6AF39353A59CE5E78FD98B57D0F3E3A7EBC8A256AC9A775BA59689F3004BF" "C3035730C4C0C51626C5D7F5852637EC589BB29DAB46C161572E4B#)\n" " (q #00DEB5A296421887179ECA1762884DE2AF8185AFC5#)\n" " (g #3958B34AE7747194ECBD312F8FEE8CBE3918E94DF9FD11E2912E56318F33BDC38622" "B18DDFF393074BCA8BAACF50DF27AEE529F3E8AEECE55C398DAB3A5E04C2EA142312" "FACA2FE7F0A88884F8DAC3979EE67598F9A383B2A2325F035C796F352A5C3CDF2CB3" "85AD24EC52A6E55247E1BB37D260F79E617D2A4446415B6AD79A#)\n" " (y #519E9FE9AB0545A6724E74603B7B04E48DC1437E0284A11EA605A7BA8AB1CF354FD4" "ECC93880AC293391C69B558AD84E7AAFA88F11D028CF3A378F241D6B056A90C588F6" "66F68D27262B4DA84657D15057D371BCEC1F6504032507D5B881E45FC93A1B973155" "D91C57219D090C3ACD75E7C2B9F1176A208AC03D6C12AC28A271#)\n" "))\n"; static const char sample_private_dsa_key_2048[] = "(private-key\n" " (dsa\n" " (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365" "A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C" "308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150" "C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970" "71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405" "D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179" "0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4" "2F9C9F315ED409171EC35CA04CC06B275577B3#)\n" " (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n" " (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78" "98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3" "5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F" "B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508" "4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F" "0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44" "2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3" "6EE4425A553AF8885FEA15A88135BE133520#)\n" " (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C" "2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB" "4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79" "328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F" "8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3" "E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923" "79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7" "14A264330AECCB24DE2A1107847B23490897#)\n" " (x #477BD14676E22563C5ABA68025CEBA2A48D485F5B2D4AD4C0EBBD6D0#)\n" "))\n"; static const char sample_public_dsa_key_2048[] = "(public-key\n" " (dsa\n" " (p #00B54636673962B64F7DC23C71ACEF6E7331796F607560B194DFCC0CA370E858A365" "A413152FB6EB8C664BD171AC316FE5B381CD084D07377571599880A068EF1382D85C" "308B4E9DEAC12D66DE5C4A826EBEB5ED94A62E7301E18927E890589A2F230272A150" "C118BC3DC2965AE0D05BE4F65C6137B2BA7EDABB192C3070D202C10AA3F534574970" "71454DB8A73DDB6511A5BA98EF1450FD90DE5BAAFC9FD3AC22EBEA612DD075BB7405" "D56866D125E33982C046808F7CEBA8E5C0B9F19A6FE451461660A1CBA9EF68891179" "0256A573D3B8F35A5C7A0C6C31F2DB90E25A26845252AD9E485EF2D339E7B5890CD4" "2F9C9F315ED409171EC35CA04CC06B275577B3#)\n" " (q #00DA67989167FDAC4AE3DF9247A716859A30C0CF9C5A6DBA01EABA3481#)\n" " (g #48E35DA584A089D05142AA63603FDB00D131B07A0781E2D5A8F9614D2B33D3E40A78" "98A9E10CDBB612CF093F95A3E10D09566726F2C12823836B2D9CD974BB695665F3B3" "5D219A9724B87F380BD5207EDA0AE38C79E8F18122C3F76E4CEB0ABED3250914987F" "B30D4B9E19C04C28A5D4F45560AF586F6A1B41751EAD90AE7F044F4E2A4A50C1F508" "4FC202463F478F678B9A19392F0D2961C5391C546EF365368BB46410C9C1CEE96E9F" "0C953570C2ED06328B11C90E86E57CAA7FA5ABAA278E22A4C8C08E16EE59F484EC44" "2CF55535BAA2C6BEA8833A555372BEFE1E665D3C7DAEF58061D5136331EF4EB61BC3" "6EE4425A553AF8885FEA15A88135BE133520#)\n" " (y #66E0D1A69D663466F8FEF2B7C0878DAC93C36A2FB2C05E0306A53B926021D4B92A1C" "2FA6860061E88E78CBBBA49B0E12700F07DBF86F72CEB2927EDAC0C7E3969C3A47BB" "4E0AE93D8BB3313E93CC7A72DFEEE442EFBC81B3B2AEC9D8DCBE21220FB760201D79" "328C41C773866587A44B6954767D022A88072900E964089D9B17133603056C985C4F" "8A0B648F297F8D2C3CB43E4371DC6002B5B12CCC085BDB2CFC5074A0587566187EE3" "E11A2A459BD94726248BB8D6CC62938E11E284C2C183576FBB51749EB238C4360923" "79C08CE1C8CD77EB57404CE9B4744395ACF721487450BADE3220576F2F816248B0A7" "14A264330AECCB24DE2A1107847B23490897#)\n" "))\n"; static const char sample_private_dsa_key_3072[] = "(private-key\n" " (dsa\n" " (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938" "877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5" "62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83" "B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988" "AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46" "0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2" "AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902" "D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60" "B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E" "95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7" "62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33" "8015353D3778B02B892AF7#)\n" " (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n" " (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4" "DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474" "7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98" "9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC" "134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C" "7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89" "F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB" "120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6" "374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0" "21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F" "D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC" "4997AF9EB55C6660B01A#)\n" " (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE" "4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053" "A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492" "8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15" "DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71" "CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997" "437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026" "73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B" "FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD" "F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765" "3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561" "2703D518D8D49FF0EBE6#)\n" " (x #00A9FFFC88E67D6F7B810E291C050BAFEA7FC4A75E8D2F16CFED3416FD77607232#)\n" "))\n"; static const char sample_public_dsa_key_3072[] = "(public-key\n" " (dsa\n" " (p #00BA73E148AEA5E8B64878AF5BE712B8302B9671C5F3EEB7722A9D0D9868D048C938" "877C91C335C7819292E69C7D34264F1578E32EC2DA8408DF75D0EB76E0D3030B84B5" "62D8EF93AB53BAB6B8A5DE464F5CA87AEA43BDCF0FB0B7815AA3114CFC84FD916A83" "B3D5FD78390189332232E9D037D215313FD002FF46C048B66703F87FAE092AAA0988" "AC745336EBE672A01DEDBD52395783579B67CF3AE1D6F1602CCCB12154FA0E00AE46" "0D9B289CF709194625BCB919B11038DEFC50ADBBA20C3F320078E4E9529B4F6848E2" "AB5E6278DB961FE226F2EEBD201E071C48C5BEF98B4D9BEE42C1C7102D893EBF8902" "D7A91266340AFD6CE1D09E52282FFF5B97EAFA3886A3FCF84FF76D1E06538D0D8E60" "B3332145785E07D29A5965382DE3470D1D888447FA9C00A2373378FC3FA7B9F7D17E" "95A6A5AE1397BE46D976EF2C96E89913AC4A09351CA661BF6F67E30407DA846946C7" "62D9BAA6B77825097D3E7B886456BB32E3E74516BF3FD93D71B257AA8F723E01CE33" "8015353D3778B02B892AF7#)\n" " (q #00BFF3F3CC18FA018A5B8155A8695E1E4939660D5E4759322C39D50F3B93E5F68B#)\n" " (g #6CCFD8219F5FCE8EF2BEF3262929787140847E38674B1EF8DB20255E212CB6330EC4" "DFE8A26AB7ECC5760DEB9BBF59A2B2821D510F1868172222867558B8D204E889C474" "7CA30FBF9D8CF41AE5D5BD845174641101593849FF333E6C93A6550931B2B9D56B98" "9CAB01729D9D736FA6D24A74D2DDE1E9E648D141473E443DD6BBF0B3CAB64F9FE4FC" "134B2EB57437789F75C744DF1FA67FA8A64603E5441BC7ECE29E00BDF262BDC81E8C" "7330A18A412DE38E7546D342B89A0AF675A89E6BEF00540EB107A2FE74EA402B0D89" "F5C02918DEEEAF8B8737AC866B09B50810AB8D8668834A1B9E1E53866E2B0A926FAB" "120A0CDE5B3715FFFE6ACD1AB73588DCC1EC4CE9392FE57F8D1D35811200CB07A0E6" "374E2C4B0AEB7E3D077B8545C0E438DCC0F1AE81E186930E99EBC5B91B77E92803E0" "21602887851A4FFDB3A7896AC655A0901218C121C5CBB0931E7D5EAC243F37711B5F" "D5A62B1B38A83F03D8F6703D8B98DF367FC8A76990335F62173A5391836F0F2413EC" "4997AF9EB55C6660B01A#)\n" " (y #2320B22434C5DB832B4EC267CC52E78DD5CCFA911E8F0804E7E7F32B186B2D4167AE" "4AA6869822E76400492D6A193B0535322C72B0B7AA4A87E33044FDC84BE24C64A053" "A37655EE9EABDCDC1FDF63F3F1C677CEB41595DF7DEFE9178D85A3D621B4E4775492" "8C0A58D2458D06F9562E4DE2FE6129A64063A99E88E54485B97484A28188C4D33F15" "DDC903B6CEA0135E3E3D27B4EA39319696305CE93D7BA7BE00367DBE3AAF43491E71" "CBF254744A5567F5D70090D6139E0C990239627B3A1C5B20B6F9F6374B8D8D8A8997" "437265BE1E3B4810D4B09254400DE287A0DFFBAEF339E48D422B1D41A37E642BC026" "73314701C8FA9792845C129351A87A945A03E6C895860E51D6FB8B7340A94D1A8A7B" "FA85AC83B4B14E73AB86CB96C236C8BFB0978B61B2367A7FE4F7891070F56C78D5DD" "F5576BFE5BE4F333A4E2664E79528B3294907AADD63F4F2E7AA8147B928D8CD69765" "3DB98C4297CB678046ED55C0DBE60BF7142C594603E4D705DC3D17270F9F086EC561" "2703D518D8D49FF0EBE6#)\n" "))\n"; static const char sample_public_elg_key_1024[] = "(public-key" " (elg" " (p #00F7CC7C08AF096B620C545C9353B1140D698FF8BE2D97A3515C17C7F8DABCDB8FB6" "64A46416C90C530C18DF5ABB6C1DDE3AE2FA9DDC9CE40DF644CDE2E759F6DE43F31A" "EEEBC136A460B3E4B0A8F99326A335145B19F4C81B13804894B7D2A30F78A8A7D7F4" "52B83836FDB0DE90BE327FB5E5318757BEF5FE0FC3A5461CBEA0D3#)" " (g #06#)" " (y #36B38FB63E3340A0DD8A0468E9FAA512A32DA010BF7110201D0A3DF1B8FEA0E16F3C" "80374584E554804B96EAA8C270FE531F75D0DBD81BA65640EDB1F76D46C27D2925B7" "3EC3B295CDAEEF242904A84D74FB2879425F82D4C5B59BB49A992F85D574168DED85" "D227600BBEF7AF0B8F0DEB785528370E4C4B3E4D65C536122A5A#)" " ))"; static const char sample_private_elg_key_1024[] = "(private-key" " (elg" " (p #00F7CC7C08AF096B620C545C9353B1140D698FF8BE2D97A3515C17C7F8DABCDB8FB6" "64A46416C90C530C18DF5ABB6C1DDE3AE2FA9DDC9CE40DF644CDE2E759F6DE43F31A" "EEEBC136A460B3E4B0A8F99326A335145B19F4C81B13804894B7D2A30F78A8A7D7F4" "52B83836FDB0DE90BE327FB5E5318757BEF5FE0FC3A5461CBEA0D3#)" " (g #06#)" " (y #36B38FB63E3340A0DD8A0468E9FAA512A32DA010BF7110201D0A3DF1B8FEA0E16F3C" "80374584E554804B96EAA8C270FE531F75D0DBD81BA65640EDB1F76D46C27D2925B7" "3EC3B295CDAEEF242904A84D74FB2879425F82D4C5B59BB49A992F85D574168DED85" "D227600BBEF7AF0B8F0DEB785528370E4C4B3E4D65C536122A5A#)" " (x #03656C6186FCD27D4A4B1F5010DC0D2AE7833B501E423FCD51DE5EB6D80DACFE#)" " ))"; static const char sample_public_elg_key_2048[] = "(public-key" " (elg" " (p #00BE5A2BB4E562D7B644E3D01321CB818DBA27295C339FC2C47EAE9823225EE1E7B6" "38C5DE300E931080E09CC89A18C9D180C16559FEF0D89D6A09534BB86489CCCEE30D" "C18E007A8726BB99F2B2D90D2694597757B120CD2435C0098AD1B74C20004C25BA97" "73EAA4FBEC594EE17F8B25867EEB0F9F857C751116ADED68ADA2A1E9F9F4F40D18F0" "EC1221CA6A746FC5F4CDA2B8B5D0AB83834564ACF6FDBB1AB01D4BFBD1E2C0108FF5" "5FB3190C6D6DA4D95EA683EFA44935CFBC0BF5C6118ACC3768AEA9A98D06024841B8" "D07C234289D22A5E3948F199C397AA991C59A55BEA0C01E91902E039116946FEA135" "768011AF6B622C5AF366EF0196FC4EAEAA8127#)" " (g #07#)" " (y #5AFF87BC23D8B97AA62897A5C1CDFFA86C59F39EDBD6012B6F333CE23D872009B8C8" "D1E220E18CFCADFE0AA16346BA2EA132472FFEC746D11C6E758896052313BB501210" "2389C683A25A3464E9B35A192BAE0A3BB99C973126F7560D968C4A754901DC967354" "D61A90ACD56D90DCC4337AFB71FAE3FD18C60EB0D6DD173877DF5DB5199C4931FE4E" "5046F814422580E1162798406FC6554781142DBB7922D4B5B37A111F23761636090F" "6212681E133365191CF15753AE737F17943ED4B7506DE0A85C3B6D63227F9D65ADF8" "2C3DF0676C8F43B5B1C07D9AD4E6D0C812401D7DA7B9484DBA8CD3B73B19A95EB237" "D493E092AEA2371AA904009C8960B0969D12#)" " ))"; static const char sample_private_elg_key_2048[] = "(private-key" " (elg" " (p #00BE5A2BB4E562D7B644E3D01321CB818DBA27295C339FC2C47EAE9823225EE1E7B6" "38C5DE300E931080E09CC89A18C9D180C16559FEF0D89D6A09534BB86489CCCEE30D" "C18E007A8726BB99F2B2D90D2694597757B120CD2435C0098AD1B74C20004C25BA97" "73EAA4FBEC594EE17F8B25867EEB0F9F857C751116ADED68ADA2A1E9F9F4F40D18F0" "EC1221CA6A746FC5F4CDA2B8B5D0AB83834564ACF6FDBB1AB01D4BFBD1E2C0108FF5" "5FB3190C6D6DA4D95EA683EFA44935CFBC0BF5C6118ACC3768AEA9A98D06024841B8" "D07C234289D22A5E3948F199C397AA991C59A55BEA0C01E91902E039116946FEA135" "768011AF6B622C5AF366EF0196FC4EAEAA8127#)" " (g #07#)" " (y #5AFF87BC23D8B97AA62897A5C1CDFFA86C59F39EDBD6012B6F333CE23D872009B8C8" "D1E220E18CFCADFE0AA16346BA2EA132472FFEC746D11C6E758896052313BB501210" "2389C683A25A3464E9B35A192BAE0A3BB99C973126F7560D968C4A754901DC967354" "D61A90ACD56D90DCC4337AFB71FAE3FD18C60EB0D6DD173877DF5DB5199C4931FE4E" "5046F814422580E1162798406FC6554781142DBB7922D4B5B37A111F23761636090F" "6212681E133365191CF15753AE737F17943ED4B7506DE0A85C3B6D63227F9D65ADF8" "2C3DF0676C8F43B5B1C07D9AD4E6D0C812401D7DA7B9484DBA8CD3B73B19A95EB237" "D493E092AEA2371AA904009C8960B0969D12#)" " (x #0628C3903972C55BDC1BC4223075616D3F3BA57D55532DDB40CB14CF72070E0D28BF" "D0402B9088D25ED8FC#)" " ))"; static const char sample_public_elg_key_3072[] = "(public-key" " (elg" " (p #008EAA3497AFE3706E1A57FFA52E68C64C500731B58EBAFEB51C4A20AB15BA57FA72" "BA1510A4703D5AA6F05DB67E4A776F92AD08800577DC686D00B793167A5D79C997E0" "5B9A9E5974B4B68B4D71ED8EC37F2F45235D901997D72915643F058E712AA18275A2" "C6F9F7C2B9B7CD1E814D215F12A840800B546AEF2A2E6C077CDD1A322738FFD36DB2" "FA5420B5848EED870BC1A6CF55040AE8D2A5945F11AE2BCBE107B41A59EFDBD3B05C" "F4C876C02C9AEAE22CD4C86806A415302936E4C1E5AA59DBBCCD2F83C20941A29888" "A70ADB94D3B8A6489C46BF2C5219CD9FD2341EA21D4E68A4ECC468FD09D215FE96D4" "7AEA12FD22B2456D2CC13672FC7E9772A365C68668157C51E46966B6A1831C429BA0" "D513519713C49C13C5FC7C14BE0A117627B204C4478D0A93C6B57929E448C9B65BF2" "390E04BC5940320C0262FC1A221E7C796493432239A6F12BC62C5CF32E8ADBC1730C" "84C6E6E6BD95AF62835941F3F344AF46BFE5A8F629D5FA699FE37EF8B8C6A2484E42" "D226206FDF7D1FB93A5457#)" " (g #0B#)" " (y #18E734FF645AE169079AEAFC78772371089AD3088627ECF77034AFBDF33ADF594AAF" "3288F6979E0DB59CE3D2F0FEE031DFF187F1E4549D3C79668794CB19C14481ECDE2D" "D50861AB674F87A011D50D35F28E424D0D2353850899C2CDD0CC8FDBFC5A0CA395F0" "E605D46CBDD140DBEF426EBD638C9ADD83C195C45CE84ED2D2B21B87800C783A4F79" "12226FEFBDA01C66B254534A51765AF09687275AA80C5DFBA143A6262E47C547D7E2" "289413F8C5C56AED3FA7E5DF5526958E2294FE318AF590C0E720029C202563E6E686" "9EC810F39A859262FB6047C1D418CAA9047A00BDB127B44B69CF6BC8E6B3709B4C23" "79783C5F8457EFE23EDA6FF00D1DDCC29268FC4A6C18577BE2B7004089CBB824027A" "A53C86B51DB054CC83B4F50C8923E2E9431F0A77D741237226CC68591083A2E40171" "5C7B74100BB74003E2264F8B44A0B0BC5404C44218ABE65C04AA573877506CE4F48C" "9E3F8AD1CD8DD9F285DD015C2FC5DEBCFA5779AD87F0BBC62E9EC6246021AB450DB9" "4DDDEFAFD2C7C66E235D#)" " ))"; static const char sample_private_elg_key_3072[] = "(private-key" " (elg" " (p #008EAA3497AFE3706E1A57FFA52E68C64C500731B58EBAFEB51C4A20AB15BA57FA72" "BA1510A4703D5AA6F05DB67E4A776F92AD08800577DC686D00B793167A5D79C997E0" "5B9A9E5974B4B68B4D71ED8EC37F2F45235D901997D72915643F058E712AA18275A2" "C6F9F7C2B9B7CD1E814D215F12A840800B546AEF2A2E6C077CDD1A322738FFD36DB2" "FA5420B5848EED870BC1A6CF55040AE8D2A5945F11AE2BCBE107B41A59EFDBD3B05C" "F4C876C02C9AEAE22CD4C86806A415302936E4C1E5AA59DBBCCD2F83C20941A29888" "A70ADB94D3B8A6489C46BF2C5219CD9FD2341EA21D4E68A4ECC468FD09D215FE96D4" "7AEA12FD22B2456D2CC13672FC7E9772A365C68668157C51E46966B6A1831C429BA0" "D513519713C49C13C5FC7C14BE0A117627B204C4478D0A93C6B57929E448C9B65BF2" "390E04BC5940320C0262FC1A221E7C796493432239A6F12BC62C5CF32E8ADBC1730C" "84C6E6E6BD95AF62835941F3F344AF46BFE5A8F629D5FA699FE37EF8B8C6A2484E42" "D226206FDF7D1FB93A5457#)" " (g #0B#)" " (y #18E734FF645AE169079AEAFC78772371089AD3088627ECF77034AFBDF33ADF594AAF" "3288F6979E0DB59CE3D2F0FEE031DFF187F1E4549D3C79668794CB19C14481ECDE2D" "D50861AB674F87A011D50D35F28E424D0D2353850899C2CDD0CC8FDBFC5A0CA395F0" "E605D46CBDD140DBEF426EBD638C9ADD83C195C45CE84ED2D2B21B87800C783A4F79" "12226FEFBDA01C66B254534A51765AF09687275AA80C5DFBA143A6262E47C547D7E2" "289413F8C5C56AED3FA7E5DF5526958E2294FE318AF590C0E720029C202563E6E686" "9EC810F39A859262FB6047C1D418CAA9047A00BDB127B44B69CF6BC8E6B3709B4C23" "79783C5F8457EFE23EDA6FF00D1DDCC29268FC4A6C18577BE2B7004089CBB824027A" "A53C86B51DB054CC83B4F50C8923E2E9431F0A77D741237226CC68591083A2E40171" "5C7B74100BB74003E2264F8B44A0B0BC5404C44218ABE65C04AA573877506CE4F48C" "9E3F8AD1CD8DD9F285DD015C2FC5DEBCFA5779AD87F0BBC62E9EC6246021AB450DB9" "4DDDEFAFD2C7C66E235D#)" " (x #03A73F0389E470AAC831B039F8AA0C4EBD3A47DD083E32EEA08E4911236CD597C272" "9823D47A51C8535DA52FE6DAB3E8D1C20D#)" " ))"; #define BUG() do {fprintf ( stderr, "Ooops at %s:%d\n", __FILE__ , __LINE__ );\ exit(2);} while(0) static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = malloc (size); if (!buf) die ("out of core\n"); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); } static void progress_cb (void *cb_data, const char *what, int printchar, int current, int total) { (void)cb_data; if (single_char_progress) { fputc (printchar, stdout); fflush (stderr); } else { fprintf (stderr, PGM ": progress (%s %c %d %d)\n", what, printchar, current, total); fflush (stderr); } } static void random_bench (int very_strong) { char buf[128]; int i; printf ("%-10s", "random"); if (!very_strong) { start_timer (); for (i=0; i < 100; i++) gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM); stop_timer (); printf (" %s", elapsed_time (1)); } start_timer (); for (i=0; i < 100; i++) gcry_randomize (buf, 8, very_strong? GCRY_VERY_STRONG_RANDOM:GCRY_STRONG_RANDOM); stop_timer (); printf (" %s", elapsed_time (1)); putchar ('\n'); if (verbose) xgcry_control ((GCRYCTL_DUMP_RANDOM_STATS)); } static void md_bench ( const char *algoname ) { int algo; gcry_md_hd_t hd; int i, j, repcount; char buf_base[1000+15]; size_t bufsize = 1000; char *buf; char *largebuf_base; char *largebuf; char digest[512/8]; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if (in_fips_mode && i == GCRY_MD_MD5) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_md_test_algo (i) ) md_bench (gcry_md_algo_name (i)); return; } buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment); algo = gcry_md_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); exit (1); } err = gcry_md_open (&hd, algo, 0); if (err) { fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname); exit (1); } for (i=0; i < bufsize; i++) buf[i] = i; printf ("%-12s", gcry_md_algo_name (algo)); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000; i++) gcry_md_write (hd, buf, bufsize); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_md_reset (hd); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 10000; i++) gcry_md_write (hd, buf, bufsize/10); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_md_reset (hd); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000000; i++) gcry_md_write (hd, buf, 1); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000; i++) for (j=0; j < bufsize; j++) gcry_md_putc (hd, buf[j]); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_md_close (hd); /* Now 100 hash operations on 10000 bytes using the fast function. We initialize the buffer so that all memory pages are committed and we have repeatable values. */ if (gcry_md_get_algo_dlen (algo) > sizeof digest) die ("digest buffer too short\n"); if (gcry_md_get_algo_dlen (algo)) { largebuf_base = malloc (10000+15); if (!largebuf_base) die ("out of core\n"); largebuf = (largebuf_base + ((16 - ((size_t)largebuf_base & 0x0f)) % buffer_alignment)); for (i=0; i < 10000; i++) largebuf[i] = i; start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 100; i++) gcry_md_hash_buffer (algo, digest, largebuf, 10000); stop_timer (); printf (" %s", elapsed_time (1)); free (largebuf_base); } putchar ('\n'); fflush (stdout); } static void mac_bench ( const char *algoname ) { int algo; gcry_mac_hd_t hd; int step, pos, j, i, repcount; char buf_base[1000+15]; size_t bufsize = 1000; char *buf; char mac[3][512]; char key[512]; unsigned int maclen, keylen; size_t macoutlen; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 600; i++) if (in_fips_mode && i == GCRY_MAC_HMAC_MD5) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_mac_test_algo (i) ) mac_bench (gcry_mac_algo_name (i)); return; } buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment); algo = gcry_mac_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid MAC algorithm `%s'\n", algoname); exit (1); } maclen = gcry_mac_get_algo_maclen (algo); if (maclen > sizeof(mac)) maclen = sizeof(mac); keylen = gcry_mac_get_algo_keylen (algo); if (keylen == 0) keylen = 32; if (keylen > sizeof(key)) keylen = sizeof(key); for (i=0; i < keylen; i++) key[i] = (keylen - i) ^ 0x54; err = gcry_mac_open (&hd, algo, 0, NULL); if (err) { fprintf (stderr, PGM ": error opening mac algorithm `%s': %s\n", algoname, gpg_strerror (err)); exit (1); } err = gcry_mac_setkey (hd, key, keylen); if (err) { fprintf (stderr, PGM ": error setting key for mac algorithm `%s': %s\n", algoname, gpg_strerror (err)); exit (1); } for (i=0; i < bufsize; i++) buf[i] = i; if (algo >= GCRY_MAC_POLY1305_AES && algo <= GCRY_MAC_POLY1305_SEED) { static const char iv[16] = { 1, 2, 3, 4, }; err = gcry_mac_setiv(hd, iv, sizeof(iv)); if (err) { fprintf (stderr, PGM ": error setting nonce for mac algorithm `%s': %s\n", algoname, gpg_strerror (err)); exit (1); } } printf ("%-20s", gcry_mac_algo_name (algo)); start_timer (); for (repcount=0; repcount < mac_repetitions; repcount++) for (i=0; i < 1000; i++) gcry_mac_write (hd, buf, bufsize); macoutlen = maclen; gcry_mac_read (hd, mac[0], &macoutlen); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_mac_reset (hd); start_timer (); for (repcount=0; repcount < mac_repetitions; repcount++) for (i=0; i < 1000; i++) for (step=bufsize/10, pos=0, j=0; j < 10; j++, pos+=step) gcry_mac_write (hd, &buf[pos], step); macoutlen = maclen; gcry_mac_read (hd, mac[1], &macoutlen); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_mac_reset (hd); start_timer (); for (repcount=0; repcount < mac_repetitions; repcount++) for (i=0; i < 1000; i++) for (step=bufsize/100, pos=0, j=0; j < 100; j++, pos+=step) gcry_mac_write (hd, &buf[pos], step); macoutlen = maclen; gcry_mac_read (hd, mac[2], &macoutlen); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_mac_close (hd); for (i=1; i < 3; i++) { if (memcmp(mac[i-1], mac[i], maclen)) { fprintf (stderr, PGM ": mac mismatch with algorithm `%s'\n", algoname); exit(1); } } putchar ('\n'); fflush (stdout); } static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen) { const int _L = 4; const int noncelen = 15 - _L; char nonce[noncelen]; u64 params[3]; gcry_error_t err = GPG_ERR_NO_ERROR; memset (nonce, 0x33, noncelen); err = gcry_cipher_setiv (hd, nonce, noncelen); if (err) { fprintf (stderr, "gcry_cipher_setiv failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } params[0] = buflen; /* encryptedlen */ params[1] = 0; /* aadlen */ params[2] = authlen; /* authtaglen */ err = gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof(params)); if (err) { fprintf (stderr, "gcry_cipher_setiv failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } static gcry_error_t cipher_encrypt (gcry_cipher_hd_t h, char *out, size_t outsize, const char *in, size_t inlen, size_t max_inlen) { gcry_error_t ret; while (inlen) { size_t currlen = inlen; if (currlen > max_inlen) currlen = max_inlen; ret = gcry_cipher_encrypt(h, out, outsize, in, currlen); if (ret) return ret; out += currlen; in += currlen; outsize -= currlen; inlen -= currlen; } return 0; } static gcry_error_t cipher_decrypt (gcry_cipher_hd_t h, char *out, size_t outsize, const char *in, size_t inlen, size_t max_inlen) { gcry_error_t ret; while (inlen) { size_t currlen = inlen; if (currlen > max_inlen) currlen = max_inlen; ret = gcry_cipher_decrypt(h, out, outsize, in, currlen); if (ret) return ret; out += currlen; in += currlen; outsize -= currlen; inlen -= currlen; } return 0; } static void cipher_bench ( const char *algoname ) { static int header_printed; int algo; gcry_cipher_hd_t hd; int i; int keylen, blklen; char key[128]; char *outbuf, *buf; char *raw_outbuf, *raw_buf; size_t allocated_buflen, buflen; int repetitions; static const struct { int mode; const char *name; int blocked; unsigned int max_inlen; void (* const aead_init)(gcry_cipher_hd_t hd, size_t buflen, int authlen); int req_blocksize; int authlen; int noncelen; int doublekey; } modes[] = { { GCRY_CIPHER_MODE_ECB, " ECB/Stream", 1, 0xffffffffU }, { GCRY_CIPHER_MODE_CBC, " CBC/Poly1305", 1, 0xffffffffU }, { GCRY_CIPHER_MODE_CFB, " CFB", 0, 0xffffffffU }, { GCRY_CIPHER_MODE_OFB, " OFB", 0, 0xffffffffU }, { GCRY_CIPHER_MODE_CTR, " CTR", 0, 0xffffffffU }, { GCRY_CIPHER_MODE_XTS, " XTS", 0, 16 << 20, NULL, GCRY_XTS_BLOCK_LEN, 0, 0, 1 }, { GCRY_CIPHER_MODE_CCM, " CCM", 0, 0xffffffffU, ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8, }, { GCRY_CIPHER_MODE_GCM, " GCM", 0, 0xffffffffU, NULL, GCRY_GCM_BLOCK_LEN, GCRY_GCM_BLOCK_LEN }, { GCRY_CIPHER_MODE_OCB, " OCB", 1, 0xffffffffU, NULL, 16, 16, 15 }, { GCRY_CIPHER_MODE_EAX, " EAX", 0, 0xffffffffU, NULL, 0, 8, 8 }, { GCRY_CIPHER_MODE_STREAM, "", 0, 0xffffffffU }, { GCRY_CIPHER_MODE_POLY1305, "", 0, 0xffffffffU, NULL, 1, 16, 12 }, {0} }; int modeidx; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if ( !gcry_cipher_test_algo (i) ) cipher_bench (gcry_cipher_algo_name (i)); return; } if (huge_buffers) { allocated_buflen = 256 * 1024 * 1024; repetitions = 4; } else if (large_buffers) { allocated_buflen = 1024 * 100; repetitions = 10; } else { allocated_buflen = 1024; repetitions = 1000; } repetitions *= cipher_repetitions; raw_buf = gcry_xcalloc (allocated_buflen+15, 1); buf = (raw_buf + ((16 - ((size_t)raw_buf & 0x0f)) % buffer_alignment)); outbuf = raw_outbuf = gcry_xmalloc (allocated_buflen+15); outbuf = (raw_outbuf + ((16 - ((size_t)raw_outbuf & 0x0f)) % buffer_alignment)); if (!header_printed) { if (cipher_repetitions != 1) printf ("Running each test %d times.\n", cipher_repetitions); printf ("%-12s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) if (*modes[modeidx].name) printf (" %-15s", modes[modeidx].name ); putchar ('\n'); printf ("%-12s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) if (*modes[modeidx].name) printf (" ---------------" ); putchar ('\n'); header_printed = 1; } algo = gcry_cipher_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname); exit (1); } keylen = gcry_cipher_get_algo_keylen (algo); if (!keylen) { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", algoname); exit (1); } if ( keylen * 2 > sizeof key ) { fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n", algo, keylen ); exit (1); } for (i=0; i < keylen * 2; i++) key[i] = i + (clock () & 0xff); blklen = gcry_cipher_get_algo_blklen (algo); if (!blklen) { fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n", algoname); exit (1); } printf ("%-12s", gcry_cipher_algo_name (algo)); fflush (stdout); for (modeidx=0; modes[modeidx].mode; modeidx++) { size_t modekeylen = keylen * (!!modes[modeidx].doublekey + 1); int is_stream = modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM || modes[modeidx].mode == GCRY_CIPHER_MODE_POLY1305; if ((blklen > 1 && is_stream) || (blklen == 1 && !is_stream)) continue; if (modes[modeidx].mode == GCRY_CIPHER_MODE_POLY1305 && algo != GCRY_CIPHER_CHACHA20) continue; /* GCM is not available in FIPS mode */ if (in_fips_mode && modes[modeidx].mode == GCRY_CIPHER_MODE_GCM) continue; if (modes[modeidx].req_blocksize > 0 && blklen != modes[modeidx].req_blocksize) { printf (" %7s %7s", "-", "-" ); continue; } for (i=0; i < sizeof buf; i++) buf[i] = i; err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname); exit (1); } if (!cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, modekeylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } buflen = allocated_buflen; if (modes[modeidx].blocked) buflen = (buflen / blklen) * blklen; start_timer (); for (i=err=0; !err && i < repetitions; i++) { if (cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, modekeylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } if (modes[modeidx].noncelen) { char nonce[100]; size_t noncelen; noncelen = modes[modeidx].noncelen; if (noncelen > sizeof nonce) noncelen = sizeof nonce; memset (nonce, 42, noncelen); err = gcry_cipher_setiv (hd, nonce, noncelen); if (err) { fprintf (stderr, "gcry_cipher_setiv failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } if (modes[modeidx].aead_init) { (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen); gcry_cipher_final (hd); err = cipher_encrypt (hd, outbuf, buflen, buf, buflen, modes[modeidx].max_inlen); if (err) break; err = gcry_cipher_gettag (hd, outbuf, modes[modeidx].authlen); } else { err = cipher_encrypt (hd, outbuf, buflen, buf, buflen, modes[modeidx].max_inlen); } } stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_encrypt failed: %s\n", gpg_strerror (err) ); exit (1); } err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname); exit (1); } if (!cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, modekeylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } start_timer (); for (i=err=0; !err && i < repetitions; i++) { if (cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, modekeylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } if (modes[modeidx].noncelen) { char nonce[100]; size_t noncelen; noncelen = modes[modeidx].noncelen; if (noncelen > sizeof nonce) noncelen = sizeof nonce; memset (nonce, 42, noncelen); err = gcry_cipher_setiv (hd, nonce, noncelen); if (err) { fprintf (stderr, "gcry_cipher_setiv failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } if (modes[modeidx].aead_init) { (*modes[modeidx].aead_init) (hd, buflen, modes[modeidx].authlen); gcry_cipher_final (hd); err = cipher_decrypt (hd, outbuf, buflen, buf, buflen, modes[modeidx].max_inlen); if (err) break; err = gcry_cipher_checktag (hd, outbuf, modes[modeidx].authlen); if (gpg_err_code (err) == GPG_ERR_CHECKSUM) err = 0; } else { gcry_cipher_final (hd); err = cipher_decrypt (hd, outbuf, buflen, buf, buflen, modes[modeidx].max_inlen); } } stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_decrypt failed: %s\n", gpg_strerror (err) ); exit (1); } } putchar ('\n'); gcry_free (raw_buf); gcry_free (raw_outbuf); } static void rsa_bench (int iterations, int print_header, int no_blinding) { gpg_error_t err; int p_sizes[] = { 1024, 2048, 3072, 4096 }; int testno; if (print_header) printf ("Algorithm generate %4d*priv %4d*public\n" "------------------------------------------------\n", iterations, iterations ); for (testno=0; testno < DIM (p_sizes); testno++) { gcry_sexp_t key_spec, key_pair, pub_key, sec_key; gcry_mpi_t x; gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; unsigned nbits = p_sizes[testno]; printf ("RSA %3d bit ", nbits); fflush (stdout); if (in_fips_mode && nbits < 2048) { puts ("[skipped in fips mode]"); continue; } err = gcry_sexp_build (&key_spec, NULL, gcry_fips_mode_active () ? "(genkey (RSA (nbits %d)))" : "(genkey (RSA (nbits %d)(transient-key)))", nbits); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); start_timer (); err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit RSA key failed: %s\n", nbits, gcry_strerror (err)); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key_pair); gcry_sexp_release (key_spec); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); x = gcry_mpi_new (nbits); gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed (%d): %s\n", count, gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); start_timer (); for (count=0; count < iterations; count++) { err = gcry_pk_verify (sig, data, pub_key); if (err) { putchar ('\n'); show_sexp ("seckey:\n", sec_key); show_sexp ("data:\n", data); show_sexp ("sig:\n", sig); die ("verify failed (%d): %s\n", count, gpg_strerror (err)); } } stop_timer (); printf (" %s", elapsed_time (1)); if (no_blinding) { fflush (stdout); x = gcry_mpi_new (nbits); gcry_mpi_randomize (x, nbits-8, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags no-blinding) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) die ("signing failed (%d): %s\n", count, gpg_strerror (err)); } stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); } putchar ('\n'); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } } static void elg_bench (int iterations, int print_header) { gpg_error_t err; gcry_sexp_t pub_key[3], sec_key[3]; int p_sizes[3] = { 1024, 2048, 3072 }; gcry_sexp_t data = NULL; gcry_sexp_t enc = NULL; gcry_sexp_t plain = NULL; int i, j; err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_elg_key_1024, strlen (sample_public_elg_key_1024)); if (!err) err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_elg_key_1024, strlen (sample_private_elg_key_1024)); if (!err) err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_elg_key_2048, strlen (sample_public_elg_key_2048)); if (!err) err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_elg_key_2048, strlen (sample_private_elg_key_2048)); if (!err) err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_elg_key_3072, strlen (sample_public_elg_key_3072)); if (!err) err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_elg_key_3072, strlen (sample_private_elg_key_3072)); if (err) { fprintf (stderr, PGM ": converting sample keys failed: %s\n", gcry_strerror (err)); exit (1); } if (print_header) printf ("Algorithm generate %4d*priv %4d*public\n" "------------------------------------------------\n", iterations, iterations ); for (i=0; i < DIM (p_sizes); i++) { char timerbuf1[100]; { gcry_mpi_t x = gcry_mpi_new (p_sizes[i]); gcry_mpi_randomize (x, p_sizes[i] - 16, GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); } if (err) { fprintf (stderr, PGM ": converting data failed: %s\n", gcry_strerror (err)); exit (1); } printf ("ELG %d bit -", p_sizes[i]); fflush (stdout); + if (in_fips_mode) + { + puts ("[skipped in fips mode]"); + goto next; + } + start_timer (); for (j=0; j < iterations; j++) { gcry_sexp_release (enc); err = gcry_pk_encrypt (&enc, data, pub_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": encrypt failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); snprintf (timerbuf1, sizeof timerbuf1, " %s", elapsed_time (1)); fflush (stdout); start_timer (); for (j=0; j < iterations; j++) { gcry_sexp_release (plain); err = gcry_pk_decrypt (&plain, enc, sec_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": decrypt failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); printf (" %s %s\n", elapsed_time (1), timerbuf1); fflush (stdout); + next: gcry_sexp_release (plain); plain = NULL; gcry_sexp_release (enc); enc = NULL; gcry_sexp_release (data); data = NULL; } for (i=0; i < DIM (p_sizes); i++) { gcry_sexp_release (sec_key[i]); gcry_sexp_release (pub_key[i]); } } static void dsa_bench (int iterations, int print_header) { gpg_error_t err; gcry_sexp_t pub_key[3], sec_key[3]; int p_sizes[3] = { 1024, 2048, 3072 }; int q_sizes[3] = { 160, 224, 256 }; gcry_sexp_t data; gcry_sexp_t sig = NULL; int i, j; err = gcry_sexp_sscan (pub_key+0, NULL, sample_public_dsa_key_1024, strlen (sample_public_dsa_key_1024)); if (!err) err = gcry_sexp_sscan (sec_key+0, NULL, sample_private_dsa_key_1024, strlen (sample_private_dsa_key_1024)); if (!err) err = gcry_sexp_sscan (pub_key+1, NULL, sample_public_dsa_key_2048, strlen (sample_public_dsa_key_2048)); if (!err) err = gcry_sexp_sscan (sec_key+1, NULL, sample_private_dsa_key_2048, strlen (sample_private_dsa_key_2048)); if (!err) err = gcry_sexp_sscan (pub_key+2, NULL, sample_public_dsa_key_3072, strlen (sample_public_dsa_key_3072)); if (!err) err = gcry_sexp_sscan (sec_key+2, NULL, sample_private_dsa_key_3072, strlen (sample_private_dsa_key_3072)); if (err) { fprintf (stderr, PGM ": converting sample keys failed: %s\n", gcry_strerror (err)); exit (1); } if (print_header) printf ("Algorithm generate %4d*priv %4d*public\n" "------------------------------------------------\n", iterations, iterations ); for (i=0; i < DIM (q_sizes); i++) { gcry_mpi_t x; x = gcry_mpi_new (q_sizes[i]); gcry_mpi_randomize (x, q_sizes[i], GCRY_WEAK_RANDOM); err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) { fprintf (stderr, PGM ": converting data failed: %s\n", gcry_strerror (err)); exit (1); } printf ("DSA %d/%d -", p_sizes[i], q_sizes[i]); fflush (stdout); - if (in_fips_mode && !(p_sizes[i] == 2048 || p_sizes[i] == 3072)) + if (in_fips_mode) { puts ("[skipped in fips mode]"); goto next; } start_timer (); for (j=0; j < iterations; j++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": signing failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); start_timer (); for (j=0; j < iterations; j++) { err = gcry_pk_verify (sig, data, pub_key[i]); if (err) { putchar ('\n'); fprintf (stderr, PGM ": verify failed: %s\n", gpg_strerror (err)); exit (1); } } stop_timer (); printf (" %s\n", elapsed_time (1)); fflush (stdout); next: gcry_sexp_release (sig); gcry_sexp_release (data); sig = NULL; } for (i=0; i < DIM (q_sizes); i++) { gcry_sexp_release (sec_key[i]); gcry_sexp_release (pub_key[i]); } } static void ecc_bench (int iterations, int print_header) { #if USE_ECC gpg_error_t err; const char *p_sizes[] = { "192", "224", "256", "384", "521", "Ed25519", "Ed448", "gost256", "gost512" }; int testno; if (print_header) printf ("Algorithm generate %4d*priv %4d*public\n" "------------------------------------------------\n", iterations, iterations ); for (testno=0; testno < DIM (p_sizes); testno++) { gcry_sexp_t key_spec, key_pair, pub_key, sec_key; gcry_mpi_t x; gcry_sexp_t data; gcry_sexp_t sig = NULL; int count; int p_size; int is_ed25519; int is_ed448; int is_gost; is_ed25519 = !strcmp (p_sizes[testno], "Ed25519"); is_ed448 = !strcmp (p_sizes[testno], "Ed448"); is_gost = !strncmp (p_sizes[testno], "gost", 4); /* Only P-{224,256,384,521} are allowed in fips mode */ if (gcry_fips_mode_active() && (is_ed25519 || is_ed448 || is_gost || !strcmp (p_sizes[testno], "192"))) continue; if (is_ed25519) { p_size = 256; printf ("EdDSA Ed25519 "); fflush (stdout); } else if (is_ed448) { p_size = 448; printf ("EdDSA Ed448 "); fflush (stdout); } else if (is_gost) { p_size = atoi (p_sizes[testno] + 4); printf ("GOST %3d bit ", p_size); fflush (stdout); } else { p_size = atoi (p_sizes[testno]); printf ("ECDSA %3d bit ", p_size); } fflush (stdout); if (is_ed25519) err = gcry_sexp_build (&key_spec, NULL, "(genkey (ecdsa (curve \"Ed25519\")" "(flags eddsa)))"); else if (is_ed448) err = gcry_sexp_build (&key_spec, NULL, "(genkey (ecdsa (curve \"Ed448\")" "(flags eddsa)))"); else if (is_gost) err = gcry_sexp_build (&key_spec, NULL, "(genkey (ecdsa (curve %s)))", p_size == 256 ? "GOST2001-test" : "GOST2012-512-test"); else err = gcry_sexp_build (&key_spec, NULL, "(genkey (ECDSA (nbits %d)))", p_size); if (err) die ("creating S-expression failed: %s\n", gcry_strerror (err)); start_timer (); err = gcry_pk_genkey (&key_pair, key_spec); if (err) die ("creating %d bit ECC key failed: %s\n", p_size, gcry_strerror (err)); if (verbose > 2) show_sexp ("ECC key:\n", key_pair); pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key_pair); gcry_sexp_release (key_spec); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); x = gcry_mpi_new (p_size); gcry_mpi_randomize (x, p_size, GCRY_WEAK_RANDOM); if (is_ed25519) err = gcry_sexp_build (&data, NULL, "(data (flags eddsa)(hash-algo sha512)" " (value %m))", x); else if (is_ed448) err = gcry_sexp_build (&data, NULL, "(data (flags eddsa)(hash-algo shake256)" " (value %m))", x); else if (is_gost) err = gcry_sexp_build (&data, NULL, "(data (flags gost) (value %m))", x); else err = gcry_sexp_build (&data, NULL, "(data (flags raw) (value %m))", x); gcry_mpi_release (x); if (err) die ("converting data failed: %s\n", gcry_strerror (err)); start_timer (); for (count=0; count < iterations; count++) { gcry_sexp_release (sig); err = gcry_pk_sign (&sig, data, sec_key); if (err) { if (verbose) { putc ('\n', stderr); show_sexp ("signing key:\n", sec_key); show_sexp ("signed data:\n", data); } die ("signing failed: %s\n", gpg_strerror (err)); } } stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); start_timer (); for (count=0; count < iterations; count++) { err = gcry_pk_verify (sig, data, pub_key); if (err) { putchar ('\n'); show_sexp ("seckey:\n", sec_key); show_sexp ("data:\n", data); show_sexp ("sig:\n", sig); die ("verify failed: %s\n", gpg_strerror (err)); } } stop_timer (); printf (" %s\n", elapsed_time (1)); fflush (stdout); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } #endif /*USE_ECC*/ } static void do_powm ( const char *n_str, const char *e_str, const char *m_str) { gcry_mpi_t e, n, msg, cip; gcry_error_t err; int i; err = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, n_str, 0, 0); if (err) BUG (); err = gcry_mpi_scan (&e, GCRYMPI_FMT_HEX, e_str, 0, 0); if (err) BUG (); err = gcry_mpi_scan (&msg, GCRYMPI_FMT_HEX, m_str, 0, 0); if (err) BUG (); cip = gcry_mpi_new (0); start_timer (); for (i=0; i < 1000; i++) gcry_mpi_powm (cip, msg, e, n); stop_timer (); printf (" %s", elapsed_time (1)); fflush (stdout); /* { */ /* char *buf; */ /* if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, (void**)&buf, NULL, cip)) */ /* BUG (); */ /* printf ("result: %s\n", buf); */ /* gcry_free (buf); */ /* } */ gcry_mpi_release (cip); gcry_mpi_release (msg); gcry_mpi_release (n); gcry_mpi_release (e); } static void mpi_bench (void) { printf ("%-10s", "powm"); fflush (stdout); do_powm ( "20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E4", "29", "B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8" ); do_powm ( "20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716", "29", "B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847" ); do_powm ( "20A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA4071620A94417D4D5EF2B2DA99165C7DC87DADB3979B72961AF90D09D59BA24CB9A10166FDCCC9C659F2B9626EC23F3FA425F564A072BA941B03FA81767CC289E41071F0246879A442658FBD18C1771571E7073EEEB2160BA0CBFB3404D627069A6CFBD53867AD2D9D40231648000787B5C84176B4336144644AE71A403CA40716", "29", "B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847B870187A323F1ECD5B8A0B4249507335A1C4CE8394F38FD76B08C78A42C58F6EA136ACF90DFE8603697B1694A3D81114D6117AC1811979C51C4DD013D52F8FC4EE4BB446B83E48ABED7DB81CBF5E81DE4759E8D68AC985846D999F96B0D8A80E5C69D272C766AB8A23B40D50A4FA889FBC2BD2624222D8EB297F4BAEF8593847" ); putchar ('\n'); } static void prime_bench (void) { gpg_error_t err; int i; gcry_mpi_t prime; int old_prog = single_char_progress; single_char_progress = 1; if (!with_progress) printf ("%-10s", "prime"); fflush (stdout); start_timer (); for (i=0; i < 10; i++) { if (with_progress) fputs ("primegen ", stdout); err = gcry_prime_generate (&prime, 1024, 0, NULL, NULL, NULL, GCRY_WEAK_RANDOM, GCRY_PRIME_FLAG_SECRET); if (with_progress) { fputc ('\n', stdout); fflush (stdout); } if (err) { fprintf (stderr, PGM ": error creating prime: %s\n", gpg_strerror (err)); exit (1); } gcry_mpi_release (prime); } stop_timer (); if (with_progress) printf ("%-10s", "prime"); printf (" %s\n", elapsed_time (1)); fflush (stdout); single_char_progress = old_prog; } int main( int argc, char **argv ) { int last_argc = -1; int no_blinding = 0; int use_secmem = 0; int pk_count = 100; buffer_alignment = 1; if (argc) { argc--; argv++; } /* We skip this test if we are running under the test suite (no args and srcdir defined) and GCRYPT_NO_BENCHMARKS is set. */ if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS")) exit (77); if (getenv ("GCRYPT_IN_REGRESSION_TEST")) { in_regression_test = 1; pk_count = 10; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: benchmark " "[md|mac|cipher|random|mpi|rsa|dsa|ecc|prime [algonames]]\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--use-secmem")) { use_secmem = 1; argc--; argv++; } else if (!strcmp (*argv, "--prefer-standard-rng")) { /* This is anyway the default, but we may want to use it for debugging. */ xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD)); argc--; argv++; } else if (!strcmp (*argv, "--prefer-fips-rng")) { xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS)); argc--; argv++; } else if (!strcmp (*argv, "--prefer-system-rng")) { xgcry_control ((GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM)); argc--; argv++; } else if (!strcmp (*argv, "--no-blinding")) { no_blinding = 1; argc--; argv++; } else if (!strcmp (*argv, "--large-buffers")) { large_buffers = 1; argc--; argv++; } else if (!strcmp (*argv, "--huge-buffers")) { huge_buffers = 1; argc--; argv++; } else if (!strcmp (*argv, "--cipher-repetitions")) { argc--; argv++; if (argc) { cipher_repetitions = atoi(*argv); argc--; argv++; } } else if (!strcmp (*argv, "--cipher-with-keysetup")) { cipher_with_keysetup = 1; argc--; argv++; } else if (!strcmp (*argv, "--hash-repetitions")) { argc--; argv++; if (argc) { hash_repetitions = atoi(*argv); argc--; argv++; } } else if (!strcmp (*argv, "--mac-repetitions")) { argc--; argv++; if (argc) { mac_repetitions = atoi(*argv); argc--; argv++; } } else if (!strcmp (*argv, "--pk-count")) { argc--; argv++; if (argc) { pk_count = atoi(*argv); argc--; argv++; } } else if (!strcmp (*argv, "--alignment")) { argc--; argv++; if (argc) { buffer_alignment = atoi(*argv); argc--; argv++; } } else if (!strcmp (*argv, "--disable-hwf")) { argc--; argv++; if (argc) { if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL)) fprintf (stderr, PGM ": unknown hardware feature `%s'" " - option ignored\n", *argv); argc--; argv++; } } else if (!strcmp (*argv, "--fips")) { argc--; argv++; /* This command needs to be called before gcry_check_version. */ xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0)); } else if (!strcmp (*argv, "--progress")) { argc--; argv++; with_progress = 1; } } if (buffer_alignment < 1 || buffer_alignment > 16) die ("value for --alignment must be in the range 1 to 16\n"); xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose)); if (!gcry_check_version (GCRYPT_VERSION)) { fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n", GCRYPT_VERSION, gcry_check_version (NULL)); exit (1); } if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; else if (!use_secmem) xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (with_progress) gcry_set_progress_handler (progress_cb, NULL); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (cipher_repetitions < 1) cipher_repetitions = 1; if (hash_repetitions < 1) hash_repetitions = 1; if (mac_repetitions < 1) mac_repetitions = 1; if (in_regression_test) fputs ("Note: " PGM " running in quick regression test mode.\n", stdout); if ( !argc ) { xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); md_bench (NULL); putchar ('\n'); mac_bench (NULL); putchar ('\n'); cipher_bench (NULL); putchar ('\n'); rsa_bench (pk_count, 1, no_blinding); elg_bench (pk_count, 0); dsa_bench (pk_count, 0); ecc_bench (pk_count, 0); putchar ('\n'); mpi_bench (); putchar ('\n'); random_bench (0); } else if ( !strcmp (*argv, "random") || !strcmp (*argv, "strongrandom")) { if (argc == 1) random_bench ((**argv == 's')); else if (argc == 2) { xgcry_control ((GCRYCTL_SET_RANDOM_SEED_FILE, argv[1])); random_bench ((**argv == 's')); xgcry_control ((GCRYCTL_UPDATE_RANDOM_SEED_FILE)); } else fputs ("usage: benchmark [strong]random [seedfile]\n", stdout); } else if ( !strcmp (*argv, "md")) { if (argc == 1) md_bench (NULL); else for (argc--, argv++; argc; argc--, argv++) md_bench ( *argv ); } else if ( !strcmp (*argv, "mac")) { if (argc == 1) mac_bench (NULL); else for (argc--, argv++; argc; argc--, argv++) mac_bench ( *argv ); } else if ( !strcmp (*argv, "cipher")) { if (argc == 1) cipher_bench (NULL); else for (argc--, argv++; argc; argc--, argv++) cipher_bench ( *argv ); } else if ( !strcmp (*argv, "mpi")) { mpi_bench (); } else if ( !strcmp (*argv, "pubkey")) { xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); rsa_bench (pk_count, 1, no_blinding); elg_bench (pk_count, 0); dsa_bench (pk_count, 0); ecc_bench (pk_count, 0); } else if ( !strcmp (*argv, "rsa")) { xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); rsa_bench (pk_count, 1, no_blinding); } else if ( !strcmp (*argv, "elg")) { xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); elg_bench (pk_count, 1); } else if ( !strcmp (*argv, "dsa")) { xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); dsa_bench (pk_count, 1); } else if ( !strcmp (*argv, "ecc")) { xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); ecc_bench (pk_count, 1); } else if ( !strcmp (*argv, "prime")) { xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); prime_bench (); } else { fprintf (stderr, PGM ": bad arguments\n"); return 1; } if (in_fips_mode && !gcry_fips_mode_active ()) fprintf (stderr, PGM ": FIPS mode is not anymore active\n"); return 0; } diff --git a/tests/dsa-rfc6979.c b/tests/dsa-rfc6979.c index 7fa4b7bd..b647efa2 100644 --- a/tests/dsa-rfc6979.c +++ b/tests/dsa-rfc6979.c @@ -1,993 +1,993 @@ /* dsa-rfc6979.c - Test for Deterministic DSA * Copyright (C) 2008 Free Software Foundation, Inc. * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #ifndef _GCRYPT_IN_LIBGCRYPT # include #endif #define PGM "dsa-rfc6979" #include "t-common.h" static int in_fips_mode = 0; static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * data_from_hex (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = gcry_xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) die ("error parsing hex string `%s'\n", string); ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; const void *a; size_t alen; void *b; size_t blen; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_data (l1, 1, &alen); b = data_from_hex (expected, &blen); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( alen != blen || memcmp (a, b, alen) ) { fail ("parameter \"%s\" does not match expected value\n", name); if (verbose) { info ("expected: %s\n", expected); show_sexp ("sexp: ", sexp); } } gcry_free (b); gcry_sexp_release (l1); } /* These test vectors are from RFC 6979. */ static void check_dsa_rfc6979 (void) { static struct { const char *name; const char *key; int fips; } keys[] = { { "DSA, 1024 bits", "(private-key" " (DSA" " (p #86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447" " E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88" " 73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C" " 881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779#)" " (q #996F967F6C8E388D9E28D01E205FBA957A5698B1#)" " (g #07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D" " 89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD" " 87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4" " 17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD#)" " (x #411602CB19A6CCC34494D79D98EF1E7ED5AF25F7#)" " (y #5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F653" " 92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D" " 4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6" " 82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B#)" " ))", 0 }, { "DSA, 2048 bits", "(private-key" " (DSA" " (p #9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" " C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" " FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" " B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" " 35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" " F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" " 92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" " 3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B#)" " (q #F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F#)" " (g #5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" " D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" " 6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" " 085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" " AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" " 3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" " BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" " DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7#)" " (x #69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC#)" " (y #667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD94" " 9F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA61" " 1728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADE" " CB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB" " 5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254" " 687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1" " 23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA" " 74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)" - " ))", 1 + " ))", 0 }, { "ECDSA, 192 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-192\")" " (q #04AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56" " 3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43#)" " (d #6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4#)" " ))", 0 }, { "ECDSA, 224 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-224\")" " (q #04" " 00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C" " EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A#)" " (d #F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1#)" " ))", 1 }, { "ECDSA, 256 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-256\")" " (q #04" " 60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6" " 7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)" " (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)" " ))", 1 }, { "ECDSA, 384 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-384\")" " (q #04" " EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64" " DEF8F0EA9055866064A254515480BC13" " 8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1" " 288B231C3AE0D4FE7344FD2533264720#)" " (d #6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8" " 96D5724E4C70A825F872C9EA60D2EDF5#)" " ))", 1 }, { "ECDSA, 521 bits (prime field)", "(private-key" " (ecdsa" " (curve \"NIST P-521\")" " (q #04" " 01894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD" " 371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F50" " 23A4" " 00493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A" " 28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFD" " FCF5#)" " (d #FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75" " CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B8" " 3538#)" " ))", 1 }, { NULL } }; static struct { const char *keyname; const char *name; const char *hashname; const char *message; const char *k, *r, *s; } tests[] = { { "DSA, 1024 bits", "With SHA-1, message = \"sample\"", "sha1", "sample", "7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B", "2E1A0C2562B2912CAAF89186FB0F42001585DA55", "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5" }, { "DSA, 1024 bits", "With SHA-224, message = \"sample\"", "sha224", "sample", "562097C06782D60C3037BA7BE104774344687649", "4BC3B686AEA70145856814A6F1BB53346F02101E", "410697B92295D994D21EDD2F4ADA85566F6F94C1" }, { "DSA, 1024 bits", "With SHA-256, message = \"sample\"", "sha256", "sample", "519BA0546D0C39202A7D34D7DFA5E760B318BCFB", "81F2F5850BE5BC123C43F71A3033E9384611C545", "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89" }, { "DSA, 1024 bits", "With SHA-384, message = \"sample\"", "sha384", "sample", "95897CD7BBB944AA932DBC579C1C09EB6FCFC595", "07F2108557EE0E3921BC1774F1CA9B410B4CE65A", "54DF70456C86FAC10FAB47C1949AB83F2C6F7595" }, { "DSA, 1024 bits", "With SHA-512, message = \"sample\"", "sha512", "sample", "09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B", "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C" }, { "DSA, 1024 bits", "With SHA-1, message = \"test\"", "sha1", "test", "5C842DF4F9E344EE09F056838B42C7A17F4A6433", "42AB2052FD43E123F0607F115052A67DCD9C5C77", "183916B0230D45B9931491D4C6B0BD2FB4AAF088" }, { "DSA, 1024 bits", "With SHA-224, message = \"test\"", "sha224", "test", "4598B8EFC1A53BC8AECD58D1ABBB0C0C71E67297", "6868E9964E36C1689F6037F91F28D5F2C30610F2", "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F" }, { "DSA, 1024 bits", "With SHA-256, message = \"test\"", "sha256", "test", "5A67592E8128E03A417B0484410FB72C0B630E1A", "22518C127299B0F6FDC9872B282B9E70D0790812", "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160" }, { "DSA, 1024 bits", "With SHA-384, message = \"test\"", "sha384", "test", "220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89", "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", "91D0E0F53E22F898D158380676A871A157CDA622" }, { "DSA, 1024 bits", "With SHA-512, message = \"test\"", "sha512", "test", "65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C", "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", "7C670C7AD72B6C050C109E1790008097125433E8" }, { "DSA, 2048 bits", "With SHA-1, message = \"sample\"", "sha1", "sample", "888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E", "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF" }, { "DSA, 2048 bits", "With SHA-224, message = \"sample\"", "sha224", "sample", "BC372967702082E1AA4FCE892209F71AE4AD25A6DFD869334E6F153BD0C4D806", "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC" }, { "DSA, 2048 bits", "With SHA-256, message = \"sample\"", "sha256", "sample", "8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52", "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53" }, { "DSA, 2048 bits", "With SHA-384, message = \"sample\"", "sha384", "sample", "C345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920", "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B" }, { "DSA, 2048 bits", "With SHA-512, message = \"sample\"", "sha512", "sample", "5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC", "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351" }, { "DSA, 2048 bits", "With SHA-1, message = \"test\"", "sha1", "test", "6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F", "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA" }, { "DSA, 2048 bits", "With SHA-224, message = \"test\"", "sha224", "test", "06BD4C05ED74719106223BE33F2D95DA6B3B541DAD7BFBD7AC508213B6DA6670", "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806" }, { "DSA, 2048 bits", "With SHA-256, message = \"test\"", "sha256", "test", "1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7", "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E" }, { "DSA, 2048 bits", "With SHA-384, message = \"test\"", "sha384", "test", "206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C", "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961" }, { "DSA, 2048 bits", "With SHA-512, message = \"test\"", "sha512", "test", "AFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA", "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1" }, { "ECDSA, 192 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", "98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", "57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64" }, { "ECDSA, 192 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8", "A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", "E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A" }, { "ECDSA, 192 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85" }, { "ECDSA, 192 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "4730005C4FCB01834C063A7B6760096DBE284B8252EF4311", "DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", "C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E" }, { "ECDSA, 192 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", "4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", "3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67" }, { "ECDSA, 192 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", "0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", "EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7" }, { "ECDSA, 192 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE", "6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", "B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293" }, { "ECDSA, 192 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F" }, { "ECDSA, 192 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693", "B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", "7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A" }, { "ECDSA, 192 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", "FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", "74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290" }, { "ECDSA, 224 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "7EEFADD91110D8DE6C2C470831387C50D3357F7F4D477054B8B426BC", "22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", "66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69" }, { "ECDSA, 224 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "C1D1F2F10881088301880506805FEB4825FE09ACB6816C36991AA06D", "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC" }, { "ECDSA, 224 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "AD3029E0278F80643DE33917CE6908C70A8FF50A411F06E41DEDFCDC", "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101" }, { "ECDSA, 224 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "52B40F5A9D3D13040F494E83D3906C6079F29981035C7BD51E5CAC40", "0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", "830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D" }, { "ECDSA, 224 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "9DB103FFEDEDF9CFDBA05184F925400C1653B8501BAB89CEA0FBEC14", "074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", "A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084" }, { "ECDSA, 224 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "2519178F82C3F0E4F87ED5883A4E114E5B7A6E374043D8EFD329C253", "DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", "95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2" }, { "ECDSA, 224 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "DF8B38D40DCA3E077D0AC520BF56B6D565134D9B5F2EAE0D34900524", "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4" }, { "ECDSA, 224 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "FF86F57924DA248D6E44E8154EB69F0AE2AEBAEE9931D0B5A969F904", "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD" }, { "ECDSA, 224 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "7046742B839478C1B5BD31DB2E862AD868E1A45C863585B5F22BDC2D", "389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", "414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB" }, { "ECDSA, 224 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "E39C2AA4EA6BE2306C72126D40ED77BF9739BB4D6EF2BBB1DCB6169D", "049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", "077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF" }, { "ECDSA, 256 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4", "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB" }, { "ECDSA, 256 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "103F90EE9DC52E5E7FB5132B7033C63066D194321491862059967C715985D473", "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C" }, { "ECDSA, 256 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "A6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60", "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8" }, { "ECDSA, 256 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4", "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954" }, { "ECDSA, 256 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5", "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE" }, { "ECDSA, 256 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E", "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1" }, { "ECDSA, 256 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "669F4426F2688B8BE0DB3A6BD1989BDAEFFF84B649EEB84F3DD26080F667FAA7", "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D" }, { "ECDSA, 256 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "D16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0", "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083" }, { "ECDSA, 256 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8", "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C" }, { "ECDSA, 256 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F", "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55" }, { "ECDSA, 384 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB09663" "0F29E5938D25106C3C340045A2DB01A7", "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA3" "7B9BA002899F6FDA3A4A9386790D4EB2", "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF" "26F49CA031D4857570CCB5CA4424A443" }, { "ECDSA, 384 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "A4E4D2F0E729EB786B31FC20AD5D849E304450E0AE8E3E341134A5C1AFA03CAB" "8083EE4E3C45B06A5899EA56C51B5879", "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366" "450F76EE3DE43F5A125333A6BE060122", "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E483" "4C082C03D83028EFBF93A3C23940CA8D" }, { "ECDSA, 384 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E" "375572342863C899F9F2EDF9747A9B60", "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33" "BDE1E888E63355D92FA2B3C36D8FB2CD", "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEB" "EFDC63ECCD1AC42EC0CB8668A4FA0AB0" }, { "ECDSA, 384 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA" "2907E3E83BA95368623B8C4686915CF9", "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C" "81A648152E44ACF96E36DD1E80FABE46", "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94F" "A329C145786E679E7B82C71A38628AC8" }, { "ECDSA, 384 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331" "A4E966532593A52980D0E3AAA5E10EC3", "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799C" "FE30F35CC900056D7C99CD7882433709", "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112" "DC7CC3EF3446DEFCEB01A45C2667FDD5" }, { "ECDSA, 384 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47" "EC3727F3A3C186C15054492E30698497", "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678" "ACD9D29876DAF46638645F7F404B11C7", "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A29916" "95BA1C84541327E966FA7B50F7382282" }, { "ECDSA, 384 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "18FA39DB95AA5F561F30FA3591DC59C0FA3653A80DAFFA0B48D1A4C6DFCBFF6E" "3D33BE4DC5EB8886A8ECD093F2935726", "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E624" "64A9A817C47FF78B8C11066B24080E72", "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C614" "1C53EA5ABEF0D8231077A04540A96B66" }, { "ECDSA, 384 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FA" "A48DD070BA79921A3457ABFF2D630AD7", "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559" "F918EEDAF2293BE5B475CC8F0188636B", "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D" "51AB373F9845C0514EEFB14024787265" }, { "ECDSA, 384 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092AD" "A71F4A459BC0DA98ADB95837DB8312EA", "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB" "0542A7F0812998DA8F1DD3CA3CF023DB", "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E0" "6A739F040649A667BF3B828246BAA5A5" }, { "ECDSA, 384 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE" "0E2CC8A136036DC4B9C00E6888F66B6C", "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D0" "6FB6495CD21B4B6E340FC236584FB277", "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B22463" "4A2092CD3792E0159AD9CEE37659C736" }, { "ECDSA, 521 bits (prime field)", "With SHA-1, message = \"sample\"", "sha1", "sample", "0089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB" "42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D" "0F9", "343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910" "FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D" "75D", "E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D" "5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5" "D16" }, { "ECDSA, 521 bits (prime field)", "With SHA-224, message = \"sample\"", "sha224", "sample", "121415EC2CD7726330A61F7F3FA5DE14BE9436019C4DB8CB4041F3B54CF31BE0" "493EE3F427FB906393D895A19C9523F3A1D54BB8702BD4AA9C99DAB2597B9211" "3F3", "01776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A3" "0715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2E" "D2E", "50CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17B" "A41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B" "41F" }, { "ECDSA, 521 bits (prime field)", "With SHA-256, message = \"sample\"", "sha256", "sample", "0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C3257576" "1793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E" "1A0", "01511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659" "D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E" "1A7", "4A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916" "E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E" "CFC" }, { "ECDSA, 521 bits (prime field)", "With SHA-384, message = \"sample\"", "sha384", "sample", "1546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FF" "AD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4" "211", "01EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4" "B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67" "451", "01F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5" "FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65" "D61" }, { "ECDSA, 521 bits (prime field)", "With SHA-512, message = \"sample\"", "sha512", "sample", "1DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F1019" "8B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBF" "FD3", "C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F1" "74E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E37" "7FA", "617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF2" "82623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A" "67A" }, { "ECDSA, 521 bits (prime field)", "With SHA-1, message = \"test\"", "sha1", "test", "0BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DD" "BA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B" "222", "013BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0" "693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0" "367", "01E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90" "F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC91679" "7FF" }, { "ECDSA, 521 bits (prime field)", "With SHA-224, message = \"test\"", "sha224", "test", "040D09FCF3C8A5F62CF4FB223CBBB2B9937F6B0577C27020A99602C25A011369" "87E452988781484EDBBCF1C47E554E7FC901BC3085E5206D9F619CFF07E73D6F" "706", "01C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086" "BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE1" "7FB", "0177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5" "BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD51" "9A4" }, { "ECDSA, 521 bits (prime field)", "With SHA-256, message = \"test\"", "sha256", "test", "01DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E84384" "1AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909" "258", "0E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D807104" "2EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656" "AA8", "CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9" "FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694" "E86" }, { "ECDSA, 521 bits (prime field)", "With SHA-384, message = \"test\"", "sha384", "test", "1F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5D" "CEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0" "C88", "014BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C" "89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF60755" "78C", "0133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0E" "D94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B" "979" }, { "ECDSA, 521 bits (prime field)", "With SHA-512, message = \"test\"", "sha512", "test", "16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1" "B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC" "56D", "013E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10" "CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47E" "E6D", "01FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78" "A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D" "CE3" }, { NULL } }; gpg_error_t err; int tno, i, hashalgo; gcry_sexp_t seckey, data, sig; unsigned char digest[64]; int digestlen; for (tno = 0; tests[tno].keyname; tno++) { if (verbose) info ("Test %d: %s. %s.\n", tno, tests[tno].keyname, tests[tno].name); { for (i=0; keys[i].name; i++) if (!strcmp (tests[tno].keyname, keys[i].name)) break; if (!keys[i].name) die ("Key '%s' used by test '%s' not found\n", tests[tno].keyname, tests[tno].name); err = gcry_sexp_new (&seckey, keys[i].key, 0, 1); if (err) die ("reading key failed: %s\n", gpg_strerror (err)); } hashalgo = gcry_md_map_name (tests[tno].hashname); if (!hashalgo) die ("hash with name '%s' is not supported\n", tests[tno].hashname); digestlen = gcry_md_get_algo_dlen (hashalgo); if (digestlen > sizeof digest) die ("internal error: digest does not fit into our buffer\n"); gcry_md_hash_buffer (hashalgo, digest, tests[tno].message, strlen (tests[tno].message)); err = gcry_sexp_build (&data, NULL, "(data " " (flags rfc6979)" " (hash %s %b))", tests[tno].hashname, digestlen, digest); if (err) die ("building data sexp failed: %s\n", gpg_strerror (err)); err = gcry_pk_sign (&sig, data, seckey); if (in_fips_mode && !keys[i].fips) { if (!err) fail ("signing should not work in FIPS mode: %s\n", gpg_strerror (err)); continue; } if (err) fail ("signing failed: %s\n", gpg_strerror (err)); extract_cmp_data (sig, "r", tests[tno].r); extract_cmp_data (sig, "s", tests[tno].s); err = gcry_pk_verify (sig, data, seckey); if (err) fail ("verification failed: %s\n", gpg_strerror (err)); gcry_sexp_release (sig); gcry_sexp_release (data); gcry_sexp_release (seckey); } } int main (int argc, char **argv) { if (argc > 1 && !strcmp (argv[1], "--verbose")) verbose = 1; else if (argc > 1 && !strcmp (argv[1], "--debug")) { verbose = 2; debug = 1; } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); /* Check that we test exactly our version - including the patchlevel. */ if (strcmp (GCRYPT_VERSION, gcry_check_version (NULL))) die ("version mismatch; pgm=%s, library=%s\n", GCRYPT_VERSION,gcry_check_version (NULL)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); /* No valuable keys are create, so we can speed up our RNG. */ xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); check_dsa_rfc6979 (); return error_count ? 1 : 0; } diff --git a/tests/fips186-dsa.c b/tests/fips186-dsa.c index 3d59dfd3..22a88892 100644 --- a/tests/fips186-dsa.c +++ b/tests/fips186-dsa.c @@ -1,574 +1,588 @@ /* fips186-dsa.c - FIPS 186 DSA tests * Copyright (C) 2008 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #ifdef _GCRYPT_IN_LIBGCRYPT # include "../src/gcrypt-int.h" #else # include #endif #define PGM "fips186-dsa" #include "t-common.h" +static int in_fips_mode = 0; static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } static gcry_mpi_t mpi_from_string (const char *string) { gpg_error_t err; gcry_mpi_t a; err = gcry_mpi_scan (&a, GCRYMPI_FMT_HEX, string, 0, NULL); if (err) die ("error converting string to mpi: %s\n", gpg_strerror (err)); return a; } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * data_from_hex (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = gcry_xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) die ("error parsing hex string `%s'\n", string); ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void extract_cmp_mpi (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; gcry_mpi_t a, b; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); b = mpi_from_string (expected); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( gcry_mpi_cmp (a, b) ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_mpi_release (b); gcry_mpi_release (a); gcry_sexp_release (l1); } static void extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; const void *a; size_t alen; void *b; size_t blen; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_data (l1, 1, &alen); b = data_from_hex (expected, &blen); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( alen != blen || memcmp (a, b, alen) ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_free (b); gcry_sexp_release (l1); } static void extract_cmp_int (gcry_sexp_t sexp, const char *name, int expected) { gcry_sexp_t l1; char *a; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_string (l1, 1); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( strtoul (a, NULL, 10) != expected ) fail ("parameter \"%s\" does not match expected value\n", name); gcry_free (a); gcry_sexp_release (l1); } static void check_dsa_gen_186_2 (void) { static struct { int nbits; const char *p, *q, *g; const char *seed; int counter; const char *h; } tbl[] = { /* These tests are from FIPS 186-2, DSAVS B.3.1 PQGGen.rsp. CAVS 2.2. */ { 1024, "d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69", "9c916d121de9a03f71fb21bc2e1c0d116f065a4f", "8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44", "0cb1990c1fd3626055d7a0096f8fa99807399871", 98, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002" }, { 1024, "f5c73304080353357de1b5967597c27d65f70aa2fe9b6aed1d0afc2b499adf22f" "8e37937096d88548ac36c4a067f8353c7fed73f96f0d688b19b0624aedbae5dbb" "0ee8835a4c269288c0e1d69479e701ee266bb767af39d748fe7d6afc73fdf44be" "3eb6e661e599670061203e75fc8b3dbd59e40b54f358d0097013a0f3867f9", "f8751166cf4f6f3b07c081fd2a9071f23ca1988d", "1e288a442e02461c418ed67a66d24cacbeb8936fbde62ff995f5fd569dee6be62" "4e4f0f9f8c8093f5d192ab3b3f9ae3f2665d95d27fb10e382f45cd356e7f4eb7a" "665db432113ed06478f93b7cf188ec7a1ee97aec8f91ea7bfceaf8b6e7e5a349c" "4ad3225362ef440c57cbc6e69df15b6699caac85f733555075f04781b2b33", "34b3520d45d240a8861b82c8b61ffa16e67b5cce", 622, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, { 1024, "c6c6f4f4eed927fb1c3b0c81010967e530658e6f9698ebe058b4f47b2dc8fcbc7" "b69296b9e8b6cf55681181fe72492668061b262b0046a0d409902e269b0cb69a4" "55ed1a086caf41927f5912bf0e0cbc45ee81a4f98bf6146f6168a228aec80e9cc" "1162d6f6aa412efe82d4f18b95e34ab790daac5bd7aef0b22fa08ba5dbaad", "d32b29f065c1394a30490b6fcbf812a32a8634ab", "06f973c879e2e89345d0ac04f9c34ad69b9eff1680f18d1c8f3e1596c2e8fa8e1" "ecef6830409e9012d4788bef6ec7414d09c981b47c941b77f39dfc49caff5e714" "c97abe25a7a8b5d1fe88700bb96eff91cca64d53700a28b1146d81bad1212d231" "80154c95a01f5aeebb553a8365c38a5ebe05539b51734233776ce9aff98b2", "b6ec750da2f824cb42c5f7e28c81350d97f75125", 185, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, { 1024, "b827a9dc9221a6ed1bec7b64d61232aacb2812f888b0a0b3a95033d7a22e77d0b" "ff23bfeed0fb1281b21b8ff7421f0c727d1fb8aa2b843d6885f067e763f83d41f" "d800ab15a7e2b12f71ec2058ee7bd62cd72c26989b272e519785da57bfa1f974b" "c652e1a2d6cfb68477de5635fd019b37add656cff0b802558b31b6d2851e5", "de822c03445b77cec4ad3a6fb0ca39ff97059ddf", "65a9e2d43a378d7063813104586868cacf2fccd51aec1e0b6af8ba3e66dee6371" "681254c3fb5e3929d65e3c4bcd20abd4ddc7cf815623e17b9fc92f02b8d44278b" "848480ffd193104cf5612639511e45bd247708ff6028bd3824f8844c263b46c69" "1f2076f8cd13c5d0be95f1f2a1a17ab1f7e5bc73500bac27d57b473ba9748", "cd2221dd73815a75224e9fde7faf52829b81ac7a", 62, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, { 1024, "898a8d93e295c8ef2ffd46976225a1543640640d155a576fafa0be32136165803" "ba2eff2782a2be75cc9ec65db6bd3238cca695b3a5a14726a2a314775c377d891" "354b3de6c89e714a05599ca04132c987f889f72c4fe298ccb31f711c03b07e1d9" "8d72af590754cf3847398b60cecd55a4611692b308809560a83880404c227", "c6d786643d2acfc6b8d576863fda8cfbfbd5e03f", "2fd38b8d21c58e8fb5315a177b8d5dc4c450d574e69348b7b9da367c26e72438d" "af8372e7f0bee84ef5dcbbc3727194a2228431192f1779be24837f22a0e14d10d" "5344da1b8b403df9f9b2655095b3d0f67418ed6cd989f35aa4232e4b7001764fb" "e85d6b2c716980f13272fc4271ac1e234f7e24c023cfc2d2dc0aa1e9af2fb", "73483e697599871af983a281e3afa22e0ed86b68", 272, "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000002", }, /* These tests are generated by the OpenSSL FIPS version. */ { 1024, "A404363903FDCE86839BCFD953AAD2DA2B0E70CAED3B5FF5D68F15A1C4BB0A793C" "A9D58FC956804C5901DE0AF99F345ED1A8617C687864BAC044B7C3C3E732A2B255" "EC986AA76EA8CB0E0815B3E0E605650AF7D8058EE7E8EBCDEFFDAB8100D3FC1033" "11BA3AB232EF06BB74BA9A949EC0C7ED324C19B202F4AB725BBB4080C9", "C643946CEA8748E12D430C48DB038F9165814389", "59B7E7BA0033CCE8E6837173420FBB382A784D4154A3C166043F5A68CB92945D16" "892D4CC5585F2D28C780E75A6C20A379E2B58304C1E5FC0D8C15E4E89C4498C8BC" "B90FB36ED8DC0489B9D0BC09EC4411FB0BFADF25485EEAB6700BE0ACF5C44A6ED7" "44A015382FF9B8DA7EAA00DEA135FADC59212DBBFFC1537336FA4B7225", "02708ab36e3f0bfd67ec3b8bd8829d03b84f56bd", 50, "02" }, { 1024, "9C664033DB8B203D826F896D2293C62EF9351D5CFD0F4C0AD7EFDA4DDC7F15987" "6A3C68CAB2586B44FD1BD4DEF7A17905D88D321DD77C4E1720D848CA21D79F9B3" "D8F537338E09B44E9F481E8DA3C56569F63146596A050EF8FAEE8ACA32C666450" "04F675C8806EB4025B0A5ECC39CE89983EA40A183A7CF5208BA958045ABD5", "AD0D8CBA369AF6CD0D2BAC0B4CFCAF0A1F9BCDF7", "74D717F7092A2AF725FDD6C2561D1DBE5AEE40203C638BA8B9F49003857873701" "95A44E515C4E8B344F5CDC7F4A6D38097CD57675E7643AB9700692C69F0A99B0E" "039FDDDFCA8CEB607BDB4ADF2834DE1690F5823FC8199FB8F6F29E5A583B6786A" "C14C7E67106C3B30568CBB9383F89287D578159778EB18216799D16D46498", "6481a12a50384888ee84b61024f7c9c685d6ac96", 289, "02" }, { 1024, "B0DFB602EB8462B1DC8C2214A52B587D3E6842CCF1C38D0F7C7F967ED30CF6828" "1E2675B3BAB594755FB1634E66B4C23936F0725A358F8DFF3C307E2601FD66D63" "5B17270450C50BD2BEC29E0E9A471DF1C15B0191517952268A2763D4BD28B8503" "B3399686272B76B11227F693D7833105EF70C2289C3194CF4527024B272DF", "EA649C04911FAB5A41440287A517EF752A40354B", "88C5A4563ECB949763E0B696CD04B21321360F54C0EE7B23E2CEDC30E9E486162" "01BFB1619E7C54B653D1F890C50E04B29205F5E3E2F93A13B0751AF25491C5194" "93C09DDF6B9C173B3846DFB0E7A5C870BBFC78419260C90E20315410691C8326C" "858D7063E7921F3F601158E912C7EE487FF259202BEEB10F6D9E99190F696", "5bf9d17bc62fbbf3d569c92bd4505586b2e5ef1a", 626, "02" }, { 1024, "F783C08D7F9463E48BA87893805C4B34B63C85DF7EBDD9EBEE94DB4AF4E4A415C" "F0F3793AE55096BA1199598798FA8403B28DED7F7C7AFD54FD535861A0150EF4D" "5871465B13837CCF46BEB0A22F8D38DC7D6AE0E14A3845FD0C027CFA97791B977" "CE2808BAD9B43CE69390C0F40016056722D82C0D7B1B27413D026A39D7DAD", "A40D9EE456AED4C8A653FDB47B6629C0B843FE8F", "DF876263E21F263AE6DA57409BD517DCEADB9216048F066D6B58867F8E59A5EEE" "700283A946C1455534618979BE6C227673C1B803910262BD93BC94D5089850614" "F3E29AB64E8C989A7E3E28FE670FFA3EE21DEEEC1AB0B60E1D8E2AA39663BADD7" "2C9F957D7F3D4F17D9FDAD050EB373A6DEFD09F5DA752EAFE046836E14B67", "8a9a57706f69f4f566252cdf6d5cbfdf2020150b", 397, "02" }, { 1024, "D40E4F6461E145859CCF60FD57962840BD75FFF12C22F76626F566842252AD068" "29745F0147056354F6C016CF12762B0E331787925B8128CF5AF81F9B176A51934" "96D792430FF83C7B79BD595BDA10787B34600787FA552EFE3662F37B99AAD3F3A" "093732680A01345192A19BECCE6BF5D498E44ED6BED5B0BA72AAD49E8276B", "D12F1BD0AA78B99247FD9F18EAFEE5C136686EA5", "468EBD20C99449C1E440E6F8E452C6A6BC7551C555FE5E94996E20CFD4DA3B9CC" "58499D6CC2374CCF9C392715A537DE10CFCA8A6A37AFBD187CF6B88D26881E5F5" "7521D9D2C9BBA51E7B87B070BBE73F5C5FE31E752CAF88183516D8503BAAC1159" "928EF50DEE52D96F396B93FB4138D786464C315401A853E57C9A0F9D25839", "30b3599944a914a330a3f49d11ec88f555422aef", 678, "02" } }; gpg_error_t err; int tno; gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values; gcry_sexp_t l1; for (tno = 0; tno < DIM (tbl); tno++) { if (verbose) info ("generating FIPS 186-2 test key %d\n", tno); { void *data; size_t datalen; data = data_from_hex (tbl[tno].seed, &datalen); err = gcry_sexp_build (&key_spec, NULL, "(genkey (dsa (nbits %d)(use-fips186-2)" "(derive-parms(seed %b))))", tbl[tno].nbits, (int)datalen, data); gcry_free (data); } if (err) die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err)); err = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (err) { - fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); + if (in_fips_mode) + { + if (verbose > 1) + fprintf (stderr, "DSA keys are not available in FIPS mode"); + } + else + fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); continue; } if (verbose > 1) show_sexp ("generated key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) fail ("public part missing in key %d\n", tno); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) fail ("private part missing in key %d\n", tno); l1 = gcry_sexp_find_token (key, "misc-key-info", 0); if (!l1) fail ("misc_key_info part missing in key %d\n", tno); seed_values = gcry_sexp_find_token (l1, "seed-values", 0); if (!seed_values) fail ("seed-values part missing in key %d\n", tno); gcry_sexp_release (l1); extract_cmp_mpi (sec_key, "p", tbl[tno].p); extract_cmp_mpi (sec_key, "q", tbl[tno].q); extract_cmp_mpi (sec_key, "g", tbl[tno].g); extract_cmp_data (seed_values, "seed", tbl[tno].seed); extract_cmp_int (seed_values, "counter", tbl[tno].counter); extract_cmp_mpi (seed_values, "h", tbl[tno].h); gcry_sexp_release (seed_values); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); gcry_sexp_release (key); } } static void check_dsa_gen_186_3 (void) { static struct { int nbits, qbits; const char *p, *q; const char *seed; int counter; } tbl[] = { /* These tests are from FIPS 186-3 Test Vectors, PQGGen.rsp. CAVS 11.1. */ { 2048, 256, "8e2266d5cb5b1e9ad34ac6380e3d166fd4d60dadc6dfa1be8492a5642c91fdf7" "e81b9634a4eeff59e7e93b1b0e8f49ded45a72788866dff71b1329feeb4b6cdb" "f2c7166c7cbca20b04300ae127c9940233e891712ac905ed6b43495717a2998e" "a8c4eef4ec6c32dc9e774e8e66476f17d9c39abac59e8b583b1107b679e0bed0" "78476e933a90cfcf80c89b831c0e054f86eac7ca848e059662d938a4e12947e2" "e73b1ffedd7125dd54ba463217abc9c5f3399132aec77b946c806429f6f812c1" "0716d57dde7b5d45cb2e5eb6e4dbb81d5a465054fa17e613cbe01afb49ea593f" "33f1a696a774941ca1ff6f208577fe529f5e7592f39698c63bf6ae9d56cd2d93", "b19c6d094e1210c92910f49aa083957fbe68c0ca4602896f50123fd776786275", "f770a4598ff756931fc529764513b103ce57d85f4ad8c5cf297c9b4d48241c5b", 105 }, { 2048, 256, "b636e5970383cecab68840cca8a909a29325c3924e2c187dd034222f9e1a4334" "1061ca620f82787bd349fb8f380fc3f0adb84be116c695529114aecee8a0a1b0" "9e7ebb6888e6da71f48eefb3e9990e2d7bd36c1aa24fb10e011a193d6b5a1b22" "6cf97fab302e237ecb1dc824264dba2e2285930005717c4e9a12cc1a1ac336c2" "0619c4d06ec4e1e02e0d1d2d285661a7472d30c4282646506487cbe6a5c988ee" "8402d474713a7d8213eeb19a0719996bbfd3835eb8832eead5a3a340e61c52f0" "0dde1c98655a13839ad215d8f43c8e482317af8b086c3d555fc8dbb2f595f256" "3520a0c6387661774e1e6ca5fe2626b26a2c4f99b7aff043a091434dfd3275b7", "fe9f06fa1901182ab00bf063bff8fd4f736922ce830fd50fee47ebbd21e291e9", "3a66a430f23374ce3d2e758881c411c23dad4a8cd6ad697056d24b8cfcc8c353", 720 }, { 2048, 256, "8d636640981c2ce1935bd16ad3aa3ce2a6efa26f23f07ceda92766f80e82fa03" "5c6cf44dc41e08fea242c5cd5846d839bdf0c11d3a29ebaca00aad844cd33a80" "448f1f96cebe66b9963f7e3b5c976e29dc430bc5ddf5d2c198eb736339adc14d" "5c8a3d22533d7c6a861b6a8b31c55e46804e4c2f95e2e9cc2bbb23bbc833995a" "7afe619127d28fa53b0712b17da4786f9116cc39e2c6254845e85513c220e368" "fe9c92bc71eabfa831062f01e66e8a970f043112ca0af175f64d13fcff2f087f" "ff9198a9fe9732001ab49b2a48d0e39f99d036698703aa853ac02c65f3d55993" "5a72c8bbc6ab2fa59ff9a2fcd837a4675229abed23d42badc12a60b34a3bf0f5", "b5f3c535e7f48d3251d353b73b3a05c4bdb4591a8c2f2ba4a6a945a889f5aeff", "77eb88f087bfbbc312bca7572bafd36f2a7aca2e4d7378dd923b0b277f3d730f", 137 }, { 2048, 256, "8fa95228b848a9533375e4789c88bb7df505c4478ed3c79545c5d2b04f0e0efb" "ac8d3f603603a48b203e1cc67ded22b840ac21bc41b7ab78c73a9cd0773148ca" "7c87a5a51564164f683e8f8a77b97cf7d91f989aa3668819bca8f54e0ec8f10c" "78ecd26982048cf0ab0446a6de154bbed8891be916627d470061811caf51bef1" "b5be8ef2b560cf981c2a097b3769bed61d6ee9b66221e956fe2c49f1809a2d5f" "6996be7b39f41afea5184a73c049f3abbd28fddbf37bcae6c4aa4a7255464c2e" "ee915c44b8d90d76e5d9e3d8e6cf4ac7c5d9436d19ccc27c5bc1b65dbb56723b" "5e77624489652313f9da2ce38554401fdbd61c78f2a4fa69bcc2f5aaffbfed2d", "ed3f52bce81572d126b27fb1e9c02346ae523532af82b79943565593d6f46d45", "e0ed96bf5e7d78754b5095ed766a1bbc4338eaa8f3d00e9906ef51a8798bc1c2", 40 }, { 2048, 256, "a80f2481a814d07eb47a7c67e24bc3f8f1ccebc6cf684a0bc9fbb0054cc24cef" "24872315b566630d5147184980b4bce3f0849660c84b22dfacb785446c0f6314" "b7a53a92cf821bcceb325e03dc9e404832146d34ff8a9b112ed0e69efe69c619" "5de03373e590eba88fc5b9d337d6566dc7e82e326a28343f644779f6784159eb" "3d33f2ddf1157a02f2f91d0897a4e8ad53f614186a5fe043187510316904bd95" "6966e10735d6ef01c195b7dd7fd245a83c18af7908fef0bced2f454e1954f2a3" "2c35658f4e0f5811a3d06c81cca715537debabbbc65ba4dd0e7fb0c08397622f" "039a51df69f5b10dda61f57bbb84c55f25eacd0f3d8b40ae016ed0ba856837e7", "9e3b5a7939082c95069902d3833df8421871ca2dab8a34f7be6cd39151291d07", "c7bb440d973189ca07464b037fd309f68ec38baba390988a2e986ecee281e2f5", 722 } }; gpg_error_t err; int tno; gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values; gcry_sexp_t l1; for (tno = 0; tno < DIM (tbl); tno++) { if (verbose) info ("generating FIPS 186-3 test key %d\n", tno); { void *data; size_t datalen; data = data_from_hex (tbl[tno].seed, &datalen); err = gcry_sexp_build (&key_spec, NULL, "(genkey (dsa (nbits %d)(qbits %d)(use-fips186)" "(derive-parms(seed %b))))", tbl[tno].nbits, tbl[tno].qbits, (int)datalen, data); gcry_free (data); } if (err) die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err)); err = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (err) { - fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); + if (in_fips_mode) + { + if (verbose > 1) + fprintf (stderr, "DSA keys are not available in FIPS mode"); + } + else + fail ("error generating key %d: %s\n", tno, gpg_strerror (err)); continue; } if (verbose > 1) show_sexp ("generated key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) fail ("public part missing in key %d\n", tno); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) fail ("private part missing in key %d\n", tno); l1 = gcry_sexp_find_token (key, "misc-key-info", 0); if (!l1) fail ("misc_key_info part missing in key %d\n", tno); seed_values = gcry_sexp_find_token (l1, "seed-values", 0); if (!seed_values) fail ("seed-values part missing in key %d\n", tno); gcry_sexp_release (l1); extract_cmp_mpi (sec_key, "p", tbl[tno].p); extract_cmp_mpi (sec_key, "q", tbl[tno].q); extract_cmp_data (seed_values, "seed", tbl[tno].seed); extract_cmp_int (seed_values, "counter", tbl[tno].counter); gcry_sexp_release (seed_values); gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); gcry_sexp_release (key); } } int main (int argc, char **argv) { if (argc > 1 && !strcmp (argv[1], "--verbose")) verbose = 1; else if (argc > 1 && !strcmp (argv[1], "--debug")) { verbose = 2; debug = 1; } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); /* No valuable keys are create, so we can speed up our RNG. */ xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); - if ( !gcry_fips_mode_active () ) - check_dsa_gen_186_2 (); + if (gcry_fips_mode_active ()) + in_fips_mode = 1; + check_dsa_gen_186_2 (); check_dsa_gen_186_3 (); return error_count ? 1 : 0; } diff --git a/tests/keygen.c b/tests/keygen.c index 4e7dfd35..5b154c94 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -1,787 +1,795 @@ /* keygen.c - key generation regression tests * Copyright (C) 2003, 2005, 2012 Free Software Foundation, Inc. * Copyright (C) 2013, 2015 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "../src/gcrypt-int.h" #define PGM "keygen" #include "t-common.h" static int in_fips_mode; /* static void */ /* show_note (const char *format, ...) */ /* { */ /* va_list arg_ptr; */ /* if (!verbose && getenv ("srcdir")) */ /* fputs (" ", stderr); /\* To align above "PASS: ". *\/ */ /* else */ /* fprintf (stderr, "%s: ", PGM); */ /* va_start (arg_ptr, format); */ /* vfprintf (stderr, format, arg_ptr); */ /* if (*format && format[strlen(format)-1] != '\n') */ /* putc ('\n', stderr); */ /* va_end (arg_ptr); */ /* } */ static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; fprintf (stderr, "%s: ", PGM); if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } static void show_mpi (const char *prefix, gcry_mpi_t a) { char *buf; void *bufaddr = &buf; gcry_error_t rc; fprintf (stderr, "%s: ", PGM); if (prefix) fputs (prefix, stderr); rc = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a); if (rc) fprintf (stderr, "[error printing number: %s]\n", gpg_strerror (rc)); else { fprintf (stderr, "%s\n", buf); gcry_free (buf); } } static void check_generated_rsa_key (gcry_sexp_t key, unsigned long expected_e) { gcry_sexp_t skey, pkey, list; pkey = gcry_sexp_find_token (key, "public-key", 0); if (!pkey) fail ("public part missing in return value\n"); else { gcry_mpi_t e = NULL; list = gcry_sexp_find_token (pkey, "e", 0); if (!list || !(e=gcry_sexp_nth_mpi (list, 1, 0)) ) fail ("public exponent not found\n"); else if (!expected_e) { if (verbose) show_mpi ("public exponent: ", e); } else if ( gcry_mpi_cmp_ui (e, expected_e)) { show_mpi ("public exponent: ", e); fail ("public exponent is not %lu\n", expected_e); } gcry_sexp_release (list); gcry_mpi_release (e); gcry_sexp_release (pkey); } skey = gcry_sexp_find_token (key, "private-key", 0); if (!skey) fail ("private part missing in return value\n"); else { int rc = gcry_pk_testkey (skey); if (rc) fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc)); gcry_sexp_release (skey); } } static void check_rsa_keys (void) { gcry_sexp_t keyparm, key; int rc; if (verbose) info ("creating 2048 bit RSA key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" " (nbits 4:2048)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc) die ("error generating RSA key: %s\n", gpg_strerror (rc)); if (verbose) info ("creating 1024 bit RSA key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" " (nbits 4:1024)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); gcry_sexp_release (key); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) fail ("error generating RSA key: %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) fail ("generating 1024 bit RSA key must not work!"); if (!rc) { if (verbose > 1) show_sexp ("1024 bit RSA key:\n", key); check_generated_rsa_key (key, 65537); } gcry_sexp_release (key); if (verbose) info ("creating 2048 bit RSA key with e=65539\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" " (nbits 4:2048)\n" " (rsa-use-e 5:65539)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc) fail ("error generating RSA key: %s\n", gpg_strerror (rc)); if (!rc) check_generated_rsa_key (key, 65539); gcry_sexp_release (key); if (verbose) info ("creating 512 bit RSA key with e=257\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" " (nbits 3:512)\n" " (rsa-use-e 3:257)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) fail ("error generating RSA key: %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) fail ("generating 512 bit RSA key must not work!"); if (verbose && rc && in_fips_mode) info ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); if (!rc) check_generated_rsa_key (key, 257); gcry_sexp_release (key); if (verbose) info ("creating 512 bit RSA key with default e\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (rsa\n" " (nbits 3:512)\n" " (rsa-use-e 1:0)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) fail ("error generating RSA key: %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) fail ("generating 512 bit RSA key must not work!"); if (verbose && rc && in_fips_mode) info ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); if (!rc) check_generated_rsa_key (key, 0); /* We don't expect a constant exponent. */ gcry_sexp_release (key); } static void check_elg_keys (void) { gcry_sexp_t keyparm, key; int rc; if (verbose) info ("creating 1024 bit Elgamal key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (elg\n" " (nbits 4:1024)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating Elgamal key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + die ("generating Elgamal key must not work in FIPS mode."); if (verbose > 1) show_sexp ("1024 bit Elgamal key:\n", key); gcry_sexp_release (key); } static void check_dsa_keys (void) { gcry_sexp_t keyparm, key; int rc; int i; /* Check that DSA generation works and that it can grok the qbits argument. */ if (verbose) info ("creating 5 1024 bit DSA keys\n"); for (i=0; i < 5; i++) { rc = gcry_sexp_new (&keyparm, "(genkey\n" " (dsa\n" " (nbits 4:1024)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) - die ("generating 1024 bit DSA key must not work!"); + die ("generating 1024 bit DSA key must not work in FIPS mode!"); if (!i && verbose > 1) show_sexp ("1024 bit DSA key:\n", key); gcry_sexp_release (key); } if (verbose) info ("creating 1536 bit DSA key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (dsa\n" " (nbits 4:1536)\n" " (qbits 3:224)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) - die ("generating 1536 bit DSA key must not work!"); + die ("generating 1536 bit DSA key must not work in FIPS mode!"); if (verbose > 1) show_sexp ("1536 bit DSA key:\n", key); gcry_sexp_release (key); if (verbose) info ("creating 3072 bit DSA key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (dsa\n" " (nbits 4:3072)\n" " (qbits 3:256)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + die ("generating DSA key must not work in FIPS mode!"); if (verbose > 1) show_sexp ("3072 bit DSA key:\n", key); gcry_sexp_release (key); if (verbose) info ("creating 2048/256 bit DSA key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (dsa\n" " (nbits 4:2048)\n" " (qbits 3:256)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + die ("generating DSA key must not work in FIPS mode!"); if (verbose > 1) show_sexp ("2048 bit DSA key:\n", key); gcry_sexp_release (key); if (verbose) info ("creating 2048/224 bit DSA key\n"); rc = gcry_sexp_new (&keyparm, "(genkey\n" " (dsa\n" " (nbits 4:2048)\n" " (qbits 3:224)\n" " ))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); - if (rc) + if (rc && !in_fips_mode) die ("error generating DSA key: %s\n", gpg_strerror (rc)); + else if (!rc && in_fips_mode) + die ("generating DSA key must not work in FIPS mode!"); if (verbose > 1) show_sexp ("2048 bit DSA key:\n", key); gcry_sexp_release (key); } static void check_generated_ecc_key (gcry_sexp_t key) { gcry_sexp_t skey, pkey; pkey = gcry_sexp_find_token (key, "public-key", 0); if (!pkey) fail ("public part missing in return value\n"); else { /* Fixme: Check more stuff. */ gcry_sexp_release (pkey); } skey = gcry_sexp_find_token (key, "private-key", 0); if (!skey) fail ("private part missing in return value\n"); else { int rc = gcry_pk_testkey (skey); if (rc) fail ("gcry_pk_testkey failed: %s\n", gpg_strerror (rc)); gcry_sexp_release (skey); } /* Finally check that gcry_pk_testkey also works on the entire S-expression. */ { int rc = gcry_pk_testkey (key); if (rc) fail ("gcry_pk_testkey failed on key pair: %s\n", gpg_strerror (rc)); } } static void check_ecc_keys (void) { const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256", "Ed25519", NULL }; int testno; gcry_sexp_t keyparm, key; int rc; for (testno=0; curves[testno]; testno++) { if (verbose) info ("creating ECC key using curve %s\n", curves[testno]); if (!strcmp (curves[testno], "Ed25519")) { /* Ed25519 isn't allowed in fips mode */ if (in_fips_mode) continue; rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve %s)(flags param eddsa)))", curves[testno]); } else rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve %s)(flags param)))", curves[testno]); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc) die ("error generating ECC key using curve %s: %s\n", curves[testno], gpg_strerror (rc)); if (verbose > 1) show_sexp ("ECC key:\n", key); check_generated_ecc_key (key); gcry_sexp_release (key); } if (verbose) info ("creating ECC key using curve Ed25519 for ECDSA\n"); rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) fail ("generating Ed25519 key must not work!"); if (verbose && rc && in_fips_mode) info ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); if (!rc) { if (verbose > 1) show_sexp ("ECC key:\n", key); check_generated_ecc_key (key); } gcry_sexp_release (key); if (verbose) info ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n"); rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)(flags nocomp)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA" " (nocomp): %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) fail ("generating Ed25519 key must not work in FIPS mode!"); if (verbose && rc && in_fips_mode) info ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); gcry_sexp_release (key); if (verbose) info ("creating ECC key using curve NIST P-384 for ECDSA\n"); /* Must be specified as nistp384 (one word), because ecc_generate * uses _gcry_sexp_nth_string which takes the first word of the name * and thus libgcrypt can't find it later in its curves table. */ rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve nistp384)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc) die ("error generating ECC key using curve NIST P-384 for ECDSA: %s\n", gpg_strerror (rc)); if (verbose > 1) show_sexp ("ECC key:\n", key); check_generated_ecc_key (key); gcry_sexp_release (key); if (verbose) info ("creating ECC key using curve NIST P-384 for ECDSA (nocomp)\n"); rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve nistp384)(flags nocomp)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc) die ("error generating ECC key using curve NIST P-384 for ECDSA" " (nocomp): %s\n", gpg_strerror (rc)); if (verbose > 1) show_sexp ("ECC key:\n", key); check_generated_ecc_key (key); gcry_sexp_release (key); if (verbose) info ("creating ECC key using curve Ed25519 for ECDSA (transient-key)\n"); rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)(flags transient-key)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA" " (transient-key): %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) fail ("generating Ed25519 key must not work in FIPS mode!"); if (verbose && rc && in_fips_mode) info ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); if (!rc) { if (verbose > 1) show_sexp ("ECC key:\n", key); check_generated_ecc_key (key); } gcry_sexp_release (key); if (verbose) info ("creating ECC key using curve Ed25519 for ECDSA " "(transient-key no-keytest)\n"); rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)" "(flags transient-key no-keytest)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc && !in_fips_mode) die ("error generating ECC key using curve Ed25519 for ECDSA" " (transient-key no-keytest): %s\n", gpg_strerror (rc)); else if (!rc && in_fips_mode) fail ("generating Ed25519 key must not work in FIPS mode!"); if (verbose && rc && in_fips_mode) info ("... correctly rejected key creation in FIPS mode (%s)\n", gpg_strerror (rc)); if (!rc) { if (verbose > 1) show_sexp ("ECC key:\n", key); check_generated_ecc_key (key); } gcry_sexp_release (key); } static void check_nonce (void) { char a[32], b[32]; int i,j; int oops=0; if (verbose) info ("checking gcry_create_nonce\n"); gcry_create_nonce (a, sizeof a); for (i=0; i < 10; i++) { gcry_create_nonce (b, sizeof b); if (!memcmp (a, b, sizeof a)) die ("identical nonce found\n"); } for (i=0; i < 10; i++) { gcry_create_nonce (a, sizeof a); if (!memcmp (a, b, sizeof a)) die ("identical nonce found\n"); } again: for (i=1,j=0; i < sizeof a; i++) if (a[0] == a[i]) j++; if (j+1 == sizeof (a)) { if (oops) die ("impossible nonce found\n"); oops++; gcry_create_nonce (a, sizeof a); goto again; } } static void progress_cb (void *cb_data, const char *what, int printchar, int current, int total) { (void)cb_data; (void)what; (void)current; (void)total; if (printchar == '\n') fputs ( "", stdout); else putchar (printchar); fflush (stdout); } static void usage (int mode) { fputs ("usage: " PGM " [options] [{rsa|elg|dsa|ecc|nonce}]\n" "Options:\n" " --verbose be verbose\n" " --debug flyswatter\n" " --fips run in FIPS mode\n" " --no-quick To not use the quick RNG hack\n" " --progress print progress indicators\n", mode? stderr : stdout); if (mode) exit (1); } int main (int argc, char **argv) { int last_argc = -1; int opt_fips = 0; int with_progress = 0; int no_quick = 0; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { usage (0); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--fips")) { argc--; argv++; opt_fips = 1; } else if (!strcmp (*argv, "--progress")) { argc--; argv++; with_progress = 1; } else if (!strcmp (*argv, "--no-quick")) { argc--; argv++; no_quick = 1; } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); else break; } xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose)); if (opt_fips) xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (!opt_fips) xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); /* No valuable keys are create, so we can speed up our RNG. */ if (!no_quick) xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); if (with_progress) gcry_set_progress_handler (progress_cb, NULL); if ( gcry_fips_mode_active () ) in_fips_mode = 1; if (opt_fips && !in_fips_mode) die ("failed to switch into FIPS mode\n"); if (!argc) { check_rsa_keys (); check_elg_keys (); check_dsa_keys (); check_ecc_keys (); check_nonce (); } else { for (; argc; argc--, argv++) if (!strcmp (*argv, "rsa")) check_rsa_keys (); else if (!strcmp (*argv, "elg")) check_elg_keys (); else if (!strcmp (*argv, "dsa")) check_dsa_keys (); else if (!strcmp (*argv, "ecc")) check_ecc_keys (); else if (!strcmp (*argv, "nonce")) check_nonce (); else usage (1); } return error_count? 1:0; } diff --git a/tests/pubkey.c b/tests/pubkey.c index 51ef0f51..751f508c 100644 --- a/tests/pubkey.c +++ b/tests/pubkey.c @@ -1,1262 +1,1323 @@ /* pubkey.c - Public key encryption/decryption tests * Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #define PGM "pubkey" #include "t-common.h" static int in_fips_mode; /* Sample RSA keys, taken from basic.c. */ static const char sample_private_key_1[] = "(private-key\n" " (openpgp-rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" " #)\n" " (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" " 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" " 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" " 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" " 83#)\n" " (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46" " 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77" " 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E" " 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9" " 19#)\n" " (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" " 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" " A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" " AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" " #)\n" " )\n" ")\n"; /* The same key as above but without p, q and u to test the non CRT case. */ static const char sample_private_key_1_1[] = "(private-key\n" " (openpgp-rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" " #)\n" " )\n" ")\n"; /* The same key as above but just without q to test the non CRT case. This should fail. */ static const char sample_private_key_1_2[] = "(private-key\n" " (openpgp-rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" " #)\n" " (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" " 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" " 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" " 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" " 83#)\n" " (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" " 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" " A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" " AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" " #)\n" " )\n" ")\n"; static const char sample_public_key_1[] = "(public-key\n" " (rsa\n" " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" " CB#)\n" " (e #010001#)\n" " )\n" ")\n"; static void show_sexp (const char *prefix, gcry_sexp_t a) { char *buf; size_t size; if (prefix) fputs (prefix, stderr); size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0); buf = gcry_xmalloc (size); gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size); fprintf (stderr, "%.*s", (int)size, buf); gcry_free (buf); } /* from ../cipher/pubkey-util.c */ static gpg_err_code_t _gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits) { char buf[50]; const char *s; size_t n; *r_nbits = 0; list = gcry_sexp_find_token (list, "nbits", 0); if (!list) return 0; /* No NBITS found. */ s = gcry_sexp_nth_data (list, 1, &n); if (!s || n >= DIM (buf) - 1 ) { /* NBITS given without a cdr. */ gcry_sexp_release (list); return GPG_ERR_INV_OBJ; } memcpy (buf, s, n); buf[n] = 0; *r_nbits = (unsigned int)strtoul (buf, NULL, 0); gcry_sexp_release (list); return 0; } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * data_from_hex (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = gcry_xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) die ("error parsing hex string `%s'\n", string); ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void extract_cmp_data (gcry_sexp_t sexp, const char *name, const char *expected) { gcry_sexp_t l1; const void *a; size_t alen; void *b; size_t blen; l1 = gcry_sexp_find_token (sexp, name, 0); a = gcry_sexp_nth_data (l1, 1, &alen); b = data_from_hex (expected, &blen); if (!a) fail ("parameter \"%s\" missing in key\n", name); else if ( alen != blen || memcmp (a, b, alen) ) { fail ("parameter \"%s\" does not match expected value\n", name); if (verbose) { info ("expected: %s\n", expected); show_sexp ("sexp: ", sexp); } } gcry_free (b); gcry_sexp_release (l1); } static void check_keys_crypt (gcry_sexp_t pkey, gcry_sexp_t skey, gcry_sexp_t plain0, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain1, cipher, l; gcry_mpi_t x0, x1; int rc; int have_flags; /* Extract data from plaintext. */ l = gcry_sexp_find_token (plain0, "value", 0); x0 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); /* Encrypt data. */ rc = gcry_pk_encrypt (&cipher, plain0, pkey); if (rc) die ("encryption failed: %s\n", gcry_strerror (rc)); l = gcry_sexp_find_token (cipher, "flags", 0); have_flags = !!l; gcry_sexp_release (l); /* Decrypt data. */ rc = gcry_pk_decrypt (&plain1, cipher, skey); gcry_sexp_release (cipher); if (rc) { if (decrypt_fail_code && gpg_err_code (rc) == decrypt_fail_code) { gcry_mpi_release (x0); return; /* This is the expected failure code. */ } die ("decryption failed: %s\n", gcry_strerror (rc)); } /* Extract decrypted data. Note that for compatibility reasons, the output of gcry_pk_decrypt depends on whether a flags lists (even if empty) occurs in its input data. Because we passed the output of encrypt directly to decrypt, such a flag value won't be there as of today. We check it anyway. */ l = gcry_sexp_find_token (plain1, "value", 0); if (l) { if (!have_flags) die ("compatibility mode of pk_decrypt broken\n"); gcry_sexp_release (plain1); x1 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); } else { if (have_flags) die ("compatibility mode of pk_decrypt broken\n"); x1 = gcry_sexp_nth_mpi (plain1, 0, GCRYMPI_FMT_USG); gcry_sexp_release (plain1); } /* Compare. */ if (gcry_mpi_cmp (x0, x1)) die ("data corrupted\n"); gcry_mpi_release (x0); gcry_mpi_release (x1); } static void check_keys (gcry_sexp_t pkey, gcry_sexp_t skey, unsigned int nbits_data, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain; gcry_mpi_t x; int rc; /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw) (value %m))", x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); gcry_mpi_release (x); /* Create plain text. */ x = gcry_mpi_new (nbits_data); gcry_mpi_randomize (x, nbits_data, GCRY_WEAK_RANDOM); rc = gcry_sexp_build (&plain, NULL, "(data (flags raw no-blinding) (value %m))", x); gcry_mpi_release (x); if (rc) die ("converting data for encryption failed: %s\n", gcry_strerror (rc)); check_keys_crypt (pkey, skey, plain, decrypt_fail_code); gcry_sexp_release (plain); } static void get_keys_sample (gcry_sexp_t *pkey, gcry_sexp_t *skey, int secret_variant) { gcry_sexp_t pub_key, sec_key; int rc; static const char *secret; switch (secret_variant) { case 0: secret = sample_private_key_1; break; case 1: secret = sample_private_key_1_1; break; case 2: secret = sample_private_key_1_2; break; default: die ("BUG\n"); } rc = gcry_sexp_sscan (&pub_key, NULL, sample_public_key_1, strlen (sample_public_key_1)); if (!rc) rc = gcry_sexp_sscan (&sec_key, NULL, secret, strlen (secret)); if (rc) die ("converting sample keys failed: %s\n", gcry_strerror (rc)); *pkey = pub_key; *skey = sec_key; } static void get_keys_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (rsa (nbits 4:2048)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) die ("error generating RSA key: %s\n", gcry_strerror (rc)); if (verbose > 1) show_sexp ("generated RSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (! pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (! sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_keys_x931_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (rsa (nbits 4:2048)(use-x931)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) die ("error generating RSA key: %s\n", gcry_strerror (rc)); if (verbose > 1) show_sexp ("generated RSA (X9.31) key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_elg_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int fixed_x) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, (fixed_x ? "(genkey (elg (nbits 4:1024)(xvalue my.not-so-secret.key)))" : "(genkey (elg (nbits 3:512)))"), 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) - die ("error generating Elgamal key: %s\n", gcry_strerror (rc)); + { + if (in_fips_mode) + { + if (verbose) + fprintf (stderr, "The Elgamal keys are not available in FIPS modee.\n"); + return; + } + die ("error generating Elgamal key: %s\n", gcry_strerror (rc)); + } if (verbose > 1) show_sexp ("generated ELG key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_dsa_key_new (gcry_sexp_t *pkey, gcry_sexp_t *skey, int transient_key) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, transient_key ? "(genkey (dsa (nbits 4:2048)(transient-key)))" : "(genkey (dsa (nbits 4:2048)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) - die ("error generating DSA key: %s\n", gcry_strerror (rc)); + { + if (in_fips_mode) + { + if (verbose) + fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); + return; + } + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + } if (verbose > 1) show_sexp ("generated DSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_dsa_key_fips186_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (dsa (nbits 4:2048)(use-fips186)))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) - die ("error generating DSA key: %s\n", gcry_strerror (rc)); + { + if (in_fips_mode) + { + if (verbose) + fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); + return; + } + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + } if (verbose > 1) show_sexp ("generated DSA key (fips 186):\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (dsa (transient-key)(domain" "(p #a8adb6c0b4cf9588012e5deff1a871d383e0e2a85b5e8e03d814fe13a059705e" "663230a377bf7323a8fa117100200bfd5adf857393b0bbd67906c081e585410e" "38480ead51684dac3a38f7b64c9eb109f19739a4517cd7d5d6291e8af20a3fbf" "17336c7bf80ee718ee087e322ee41047dabefbcc34d10b66b644ddb3160a28c0" "639563d71993a26543eadb7718f317bf5d9577a6156561b082a10029cd44012b" "18de6844509fe058ba87980792285f2750969fe89c2cd6498db3545638d5379d" "125dccf64e06c1af33a6190841d223da1513333a7c9d78462abaab31b9f96d5f" "34445ceb6309f2f6d2c8dde06441e87980d303ef9a1ff007e8be2f0be06cc15f#)" "(q #e71f8567447f42e75f5ef85ca20fe557ab0343d37ed09edc3f6e68604d6b9dfb#)" "(g #5ba24de9607b8998e66ce6c4f812a314c6935842f7ab54cd82b19fa104abfb5d" "84579a623b2574b37d22ccae9b3e415e48f5c0f9bcbdff8071d63b9bb956e547" "af3a8df99e5d3061979652ff96b765cb3ee493643544c75dbe5bb39834531952" "a0fb4b0378b3fcbb4c8b5800a5330392a2a04e700bb6ed7e0b85795ea38b1b96" "2741b3f33b9dde2f4ec1354f09e2eb78e95f037a5804b6171659f88715ce1a9b" "0cc90c27f35ef2f10ff0c7c7a2bb0154d9b8ebe76a3d764aa879af372f4240de" "8347937e5a90cec9f41ff2f26b8da9a94a225d1a913717d73f10397d2183f1ba" "3b7b45a68f1ff1893caf69a827802f7b6a48d51da6fbefb64fd9a6c5b75c4561#)" ")))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) - die ("error generating DSA key: %s\n", gcry_strerror (rc)); + { + if (in_fips_mode) + { + if (verbose) + fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); + return; + } + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + } if (verbose > 1) show_sexp ("generated DSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } #if 0 static void get_dsa_key_fips186_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey (dsa (transient-key)(use-fips186)(domain" "(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)" "(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)" "(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)" ")))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) die ("error generating DSA key: %s\n", gcry_strerror (rc)); if (verbose > 1) show_sexp ("generated DSA key:\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } #endif /*0*/ static void get_dsa_key_fips186_with_seed_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) { gcry_sexp_t key_spec, key, pub_key, sec_key; int rc; rc = gcry_sexp_new (&key_spec, "(genkey" " (dsa" " (nbits 4:2048)" " (qbits 3:256)" " (use-fips186)" " (transient-key)" " (derive-parms" " (seed #f770a4598ff756931fc529764513b103ce57d85f4ad8c5cf297c9b4d48241c5b#))))", 0, 1); if (rc) die ("error creating S-expression: %s\n", gcry_strerror (rc)); rc = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (rc) - die ("error generating DSA key: %s\n", gcry_strerror (rc)); + { + if (in_fips_mode) + { + if (verbose) + fprintf (stderr, "The DSA keys are not available in FIPS modee.\n"); + return; + } + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + } if (verbose > 1) show_sexp ("generated DSA key (fips 186 with seed):\n", key); pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key\n"); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key\n"); gcry_sexp_release (key); *pkey = pub_key; *skey = sec_key; } static void check_run (void) { gpg_error_t err; gcry_sexp_t pkey, skey; int variant; for (variant=0; variant < 3; variant++) { if (verbose) fprintf (stderr, "Checking sample key (%d).\n", variant); get_keys_sample (&pkey, &skey, variant); /* Check gcry_pk_testkey which requires all elements. */ err = gcry_pk_testkey (skey); if ((variant == 0 && err) || (variant > 0 && gpg_err_code (err) != GPG_ERR_NO_OBJ)) die ("gcry_pk_testkey failed: %s\n", gpg_strerror (err)); /* Run the usual check but expect an error from variant 2. */ check_keys (pkey, skey, 800, variant == 2? GPG_ERR_NO_OBJ : 0); gcry_sexp_release (pkey); gcry_sexp_release (skey); } if (verbose) fprintf (stderr, "Checking generated RSA key.\n"); get_keys_new (&pkey, &skey); check_keys (pkey, skey, 800, 0); gcry_sexp_release (pkey); gcry_sexp_release (skey); if (verbose) fprintf (stderr, "Checking generated RSA key (X9.31).\n"); get_keys_x931_new (&pkey, &skey); check_keys (pkey, skey, 800, 0); gcry_sexp_release (pkey); gcry_sexp_release (skey); if (verbose) fprintf (stderr, "Checking generated Elgamal key.\n"); get_elg_key_new (&pkey, &skey, 0); - check_keys (pkey, skey, 400, 0); - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + if (!in_fips_mode) + { + check_keys (pkey, skey, 400, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } if (verbose) fprintf (stderr, "Checking passphrase generated Elgamal key.\n"); get_elg_key_new (&pkey, &skey, 1); - check_keys (pkey, skey, 800, 0); - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + if (!in_fips_mode) + { + check_keys (pkey, skey, 800, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } if (verbose) fprintf (stderr, "Generating DSA key.\n"); get_dsa_key_new (&pkey, &skey, 0); - /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + if (!in_fips_mode) + { + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } if (verbose) fprintf (stderr, "Generating transient DSA key.\n"); get_dsa_key_new (&pkey, &skey, 1); - /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + if (!in_fips_mode) + { + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } if (verbose) fprintf (stderr, "Generating DSA key (FIPS 186).\n"); get_dsa_key_fips186_new (&pkey, &skey); - /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + if (!in_fips_mode) + { + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } if (verbose) fprintf (stderr, "Generating DSA key with given domain.\n"); get_dsa_key_with_domain_new (&pkey, &skey); - /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + if (!in_fips_mode) + { + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } /* We need new test vectors for get_dsa_key_fips186_with_domain_new. */ if (verbose) fprintf (stderr, "Generating DSA key with given domain (FIPS 186)" " - skipped.\n"); /* get_dsa_key_fips186_with_domain_new (&pkey, &skey); */ /* /\* Fixme: Add a check function for DSA keys. *\/ */ /* gcry_sexp_release (pkey); */ /* gcry_sexp_release (skey); */ if (verbose) fprintf (stderr, "Generating DSA key with given seed (FIPS 186).\n"); get_dsa_key_fips186_with_seed_new (&pkey, &skey); - /* Fixme: Add a check function for DSA keys. */ - gcry_sexp_release (pkey); - gcry_sexp_release (skey); + if (!in_fips_mode) + { + /* Fixme: Add a check function for DSA keys. */ + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + } } static gcry_mpi_t key_param_from_sexp (gcry_sexp_t sexp, const char *topname, const char *name) { gcry_sexp_t l1, l2; gcry_mpi_t result; l1 = gcry_sexp_find_token (sexp, topname, 0); if (!l1) return NULL; l2 = gcry_sexp_find_token (l1, name, 0); if (!l2) { gcry_sexp_release (l1); return NULL; } result = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l2); gcry_sexp_release (l1); return result; } static void check_x931_derived_key (int what) { static struct { const char *param; const char *expected_d; } testtable[] = { { /* First example from X9.31 (D.1.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1024)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #1A1916DDB29B4EB7EB6732E128#)\n" " (Xp2 #192E8AAC41C576C822D93EA433#)\n" " (Xp #D8CD81F035EC57EFE822955149D3BFF70C53520D\n" " 769D6D76646C7A792E16EBD89FE6FC5B605A6493\n" " 39DFC925A86A4C6D150B71B9EEA02D68885F5009\n" " B98BD984#)\n" " (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)\n" " (Xq2 #134E4CAA16D2350A21D775C404#)\n" " (Xq #CC1092495D867E64065DEE3E7955F2EBC7D47A2D\n" " 7C9953388F97DDDC3E1CA19C35CA659EDC2FC325\n" " 6D29C2627479C086A699A49C4C9CEE7EF7BD1B34\n" " 321DE34A#))))\n", "1CCDA20BCFFB8D517EE9666866621B11822C7950D55F4BB5BEE37989A7D173" "12E326718BE0D79546EAAE87A56623B919B1715FFBD7F16028FC4007741961" "C88C5D7B4DAAAC8D36A98C9EFBB26C8A4A0E6BC15B358E528A1AC9D0F042BE" "B93BCA16B541B33F80C933A3B769285C462ED5677BFE89DF07BED5C127FD13" "241D3C4B" }, { /* Second example from X9.31 (D.2.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1536)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #18272558B61316348297EACA74#)\n" " (Xp2 #1E970E8C6C97CEF91F05B0FA80#)\n" " (Xp #F7E943C7EF2169E930DCF23FE389EF7507EE8265\n" " 0D42F4A0D3A3CEFABE367999BB30EE680B2FE064\n" " 60F707F46005F8AA7CBFCDDC4814BBE7F0F8BC09\n" " 318C8E51A48D134296E40D0BBDD282DCCBDDEE1D\n" " EC86F0B1C96EAFF5CDA70F9AEB6EE31E#)\n" " (Xq1 #11FDDA6E8128DC1629F75192BA#)\n" " (Xq2 #18AB178ECA907D72472F65E480#)\n" " (Xq #C47560011412D6E13E3E7D007B5C05DBF5FF0D0F\n" " CFF1FA2070D16C7ABA93EDFB35D8700567E5913D\n" " B734E3FBD15862EBC59FA0425DFA131E549136E8\n" " E52397A8ABE4705EC4877D4F82C4AAC651B33DA6\n" " EA14B9D5F2A263DC65626E4D6CEAC767#))))\n", "1FB56069985F18C4519694FB71055721A01F14422DC901C35B03A64D4A5BD1" "259D573305F5B056AC931B82EDB084E39A0FD1D1A86CC5B147A264F7EF4EB2" "0ED1E7FAAE5CAE4C30D5328B7F74C3CAA72C88B70DED8EDE207B8629DA2383" "B78C3CE1CA3F9F218D78C938B35763AF2A8714664CC57F5CECE2413841F5E9" "EDEC43B728E25A41BF3E1EF8D9EEE163286C9F8BF0F219D3B322C3E4B0389C" "2E8BB28DC04C47DA2BF38823731266D2CF6CC3FC181738157624EF051874D0" "BBCCB9F65C83" /* Note that this example in X9.31 gives this value for D: "7ED581A6617C6311465A53EDC4155C86807C5108B724070D6C0E9935296F44" "96755CCC17D6C15AB24C6E0BB6C2138E683F4746A1B316C51E8993DFBD3AC8" "3B479FEAB972B930C354CA2DFDD30F2A9CB222DC37B63B7881EE18A7688E0E" "DE30F38728FE7C8635E324E2CD5D8EBCAA1C51993315FD73B38904E107D7A7" "B7B10EDCA3896906FCF87BE367BB858CA1B27E2FC3C8674ECC8B0F92C0E270" "BA2ECA3701311F68AFCE208DCC499B4B3DB30FF0605CE055D893BC1461D342" "EF32E7D9720B" This is a bug in X9.31, obviously introduced by using d = e^{-1} mod (p-1)(q-1) instead of using the universal exponent as required by 4.1.3: d = e^{-1} mod lcm(p-1,q-1) The examples in X9.31 seem to be pretty buggy, see cipher/primegen.c for another bug. Not only that I had to spend 100 USD for the 66 pages of the document, it also took me several hours to figure out that the bugs are in the document and not in my code. */ }, { /* First example from NIST RSAVS (B.1.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1024)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #1ed3d6368e101dab9124c92ac8#)\n" " (Xp2 #16e5457b8844967ce83cab8c11#)\n" " (Xp #b79f2c2493b4b76f329903d7555b7f5f06aaa5ea\n" " ab262da1dcda8194720672a4e02229a0c71f60ae\n" " c4f0d2ed8d49ef583ca7d5eeea907c10801c302a\n" " cab44595#)\n" " (Xq1 #1a5d9e3fa34fb479bedea412f6#)\n" " (Xq2 #1f9cca85f185341516d92e82fd#)\n" " (Xq #c8387fd38fa33ddcea6a9de1b2d55410663502db\n" " c225655a9310cceac9f4cf1bce653ec916d45788\n" " f8113c46bc0fa42bf5e8d0c41120c1612e2ea8bb\n" " 2f389eda#))))\n", "17ef7ad4fd96011b62d76dfb2261b4b3270ca8e07bc501be954f8719ef586b" "f237e8f693dd16c23e7adecc40279dc6877c62ab541df5849883a5254fccfd" "4072a657b7f4663953930346febd6bbd82f9a499038402cbf97fd5f068083a" "c81ad0335c4aab0da19cfebe060a1bac7482738efafea078e21df785e56ea0" "dc7e8feb" }, { /* Second example from NIST RSAVS (B.1.1). */ "(genkey\n" " (rsa\n" " (nbits 4:1536)\n" " (rsa-use-e 1:3)\n" " (derive-parms\n" " (Xp1 #1e64c1af460dff8842c22b64d0#)\n" " (Xp2 #1e948edcedba84039c81f2ac0c#)\n" " (Xp #c8c67df894c882045ede26a9008ab09ea0672077\n" " d7bc71d412511cd93981ddde8f91b967da404056\n" " c39f105f7f239abdaff92923859920f6299e82b9\n" " 5bd5b8c959948f4a034d81613d6235a3953b49ce\n" " 26974eb7bb1f14843841281b363b9cdb#)\n" " (Xq1 #1f3df0f017ddd05611a97b6adb#)\n" " (Xq2 #143edd7b22d828913abf24ca4d#)\n" " (Xq #f15147d0e7c04a1e3f37adde802cdc610999bf7a\n" " b0088434aaeda0c0ab3910b14d2ce56cb66bffd9\n" " 7552195fae8b061077e03920814d8b9cfb5a3958\n" " b3a82c2a7fc97e55db543948d3396289245336ec\n" " 9e3cb308cc655aebd766340da8921383#))))\n", "1f8b19f3f5f2ac9fc599f110cad403dcd9bdf5f7f00fb2790e78e820398184" "1f3fb3dd230fb223d898f45719d9b2d3525587ff2b8bcc7425e40550a5b536" "1c8e9c1d26e83fbd9c33c64029c0e878b829d55def12912b73d94fd758c461" "0f473e230c41b5e4c86e27c5a5029d82c811c88525d0269b95bd2ff272994a" "dbd80f2c2ecf69065feb8abd8b445b9c6d306b1585d7d3d7576d49842bc7e2" "8b4a2f88f4a47e71c3edd35fdf83f547ea5c2b532975c551ed5268f748b2c4" "2ccf8a84835b" } }; gpg_error_t err; gcry_sexp_t key_spec = NULL, key = NULL, pub_key = NULL, sec_key = NULL; gcry_mpi_t d_expected = NULL, d_have = NULL; if (what < 0 && what >= sizeof testtable) die ("invalid WHAT value\n"); err = gcry_sexp_new (&key_spec, testtable[what].param, 0, 1); if (err) die ("error creating S-expression [%d]: %s\n", what, gpg_strerror (err)); { unsigned nbits; err = _gcry_pk_util_get_nbits(key_spec, &nbits); if (err) die ("nbits not found\n"); if (in_fips_mode && nbits < 2048) { info("RSA key test with %d bits skipped in fips mode\n", nbits); goto leave; } } err = gcry_pk_genkey (&key, key_spec); gcry_sexp_release (key_spec); if (err) { fail ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err)); goto leave; } pub_key = gcry_sexp_find_token (key, "public-key", 0); if (!pub_key) die ("public part missing in key [%d]\n", what); sec_key = gcry_sexp_find_token (key, "private-key", 0); if (!sec_key) die ("private part missing in key [%d]\n", what); err = gcry_mpi_scan (&d_expected, GCRYMPI_FMT_HEX, testtable[what].expected_d, 0, NULL); if (err) die ("error converting string [%d]\n", what); if (verbose > 1) show_sexp ("generated key:\n", key); d_have = key_param_from_sexp (sec_key, "rsa", "d"); if (!d_have) die ("parameter d not found in RSA secret key [%d]\n", what); if (gcry_mpi_cmp (d_expected, d_have)) { show_sexp (NULL, sec_key); die ("parameter d does match expected value [%d]\n", what); } leave: gcry_mpi_release (d_expected); gcry_mpi_release (d_have); gcry_sexp_release (key); gcry_sexp_release (pub_key); gcry_sexp_release (sec_key); } static void check_ecc_sample_key (void) { static const char ecc_private_key[] = "(private-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781" "B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)\n" " (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)" "))"; static const char ecc_private_key_wo_q[] = "(private-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (d #5A1EF0035118F19F3110FB81813D3547BCE1E5BCE77D1F744715E1D5BBE70378#)" "))"; static const char ecc_public_key[] = "(public-key\n" " (ecdsa\n" " (curve \"NIST P-256\")\n" " (q #04D4F6A6738D9B8D3A7075C1E4EE95015FC0C9B7E4272D2BEB6644D3609FC781" "B71F9A8072F58CB66AE2F89BB12451873ABF7D91F9E1FBF96BF2F70E73AAC9A283#)" "))"; static const char hash_string[] = "(data (flags raw)\n" " (value #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; static const char hash2_string[] = "(data (flags raw)\n" " (hash sha1 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "00112233445566778899AABBCCDDEEFF#))"; /* hash2, but longer than curve length, so it will be truncated */ static const char hash3_string[] = "(data (flags raw)\n" " (hash sha1 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "000102030405060708090A0B0C0D0E0F" /* */ "00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; gpg_error_t err; gcry_sexp_t key, hash, hash2, hash3, sig, sig2; if (verbose) fprintf (stderr, "Checking sample ECC key.\n"); if ((err = gcry_sexp_new (&hash, hash_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&hash2, hash2_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&hash3, hash3_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Verify hash truncation */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig2, hash2, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash3, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash2, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); if ((err = gcry_pk_verify (sig2, hash3, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Now try signing without the Q parameter. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign without Q failed: %s", gpg_strerror (err)); gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed without Q failed: %s", gpg_strerror (err)); gcry_sexp_release (sig); gcry_sexp_release (sig2); gcry_sexp_release (key); gcry_sexp_release (hash); gcry_sexp_release (hash2); gcry_sexp_release (hash3); } static void check_ed25519ecdsa_sample_key (void) { static const char ecc_private_key[] = "(private-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321" " 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)" " (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)" "))"; static const char ecc_private_key_wo_q[] = "(private-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (d #09A0C38E0F1699073541447C19DA12E3A07A7BFDB0C186E4AC5BCE6F23D55252#)" "))"; static const char ecc_public_key[] = "(public-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #044C056555BE4084BB3D8D8895FDF7C2893DFE0256251923053010977D12658321" " 156D1ADDC07987713A418783658B476358D48D582DB53233D9DED3C1C2577B04#)" "))"; static const char ecc_public_key_comp[] = "(public-key\n" " (ecc\n" " (curve \"Ed25519\")\n" " (q #047b57c2c1d3ded93332b52d588dd45863478b658387413a718779c0dd1a6d95#)" "))"; static const char hash_string[] = "(data (flags rfc6979)\n" " (hash sha256 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; gpg_error_t err; gcry_sexp_t key, hash, sig; if (verbose) fprintf (stderr, "Checking sample Ed25519/ECDSA key.\n"); /* Sign. */ if ((err = gcry_sexp_new (&hash, hash_string, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_sexp_new (&key, ecc_private_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign failed: %s", gpg_strerror (err)); /* Verify. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed: %s", gpg_strerror (err)); /* Verify again using a compressed public key. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify failed (comp): %s", gpg_strerror (err)); /* Sign without a Q parameter. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_private_key_wo_q, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); gcry_sexp_release (sig); if ((err = gcry_pk_sign (&sig, hash, key))) die ("gcry_pk_sign w/o Q failed: %s", gpg_strerror (err)); /* Verify. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed w/o Q failed: %s", gpg_strerror (err)); /* Verify again using a compressed public key. */ gcry_sexp_release (key); if ((err = gcry_sexp_new (&key, ecc_public_key_comp, 0, 1))) die ("line %d: %s", __LINE__, gpg_strerror (err)); if ((err = gcry_pk_verify (sig, hash, key))) die ("gcry_pk_verify signed w/o Q failed (comp): %s", gpg_strerror (err)); extract_cmp_data (sig, "r", ("a63123a783ef29b8276e08987daca4" "655d0179e22199bf63691fd88eb64e15")); extract_cmp_data (sig, "s", ("0d9b45c696ab90b96b08812b485df185" "623ddaf5d02fa65ca5056cb6bd0f16f1")); gcry_sexp_release (sig); gcry_sexp_release (key); gcry_sexp_release (hash); } int main (int argc, char **argv) { int i; if (argc > 1 && !strcmp (argv[1], "--verbose")) verbose = 1; else if (argc > 1 && !strcmp (argv[1], "--debug")) { verbose = 2; debug = 1; } xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); /* No valuable keys are create, so we can speed up our RNG. */ xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; for (i=0; i < 2; i++) check_run (); for (i=0; i < 4; i++) check_x931_derived_key (i); check_ecc_sample_key (); if (!in_fips_mode) check_ed25519ecdsa_sample_key (); return !!error_count; } diff --git a/tests/t-dsa.c b/tests/t-dsa.c index c0175510..e82db62d 100644 --- a/tests/t-dsa.c +++ b/tests/t-dsa.c @@ -1,621 +1,627 @@ /* t-dsa.c - Check the DSA crypto * Copyright (C) 2021 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "stopwatch.h" #define PGM "t-dsa" #include "t-common.h" #define N_TESTS 300 static int no_verify; static int custom_data_file; static int in_fips_mode = 0; static void show_note (const char *format, ...) { va_list arg_ptr; if (!verbose && getenv ("srcdir")) fputs (" ", stderr); /* To align above "PASS: ". */ else fprintf (stderr, "%s: ", PGM); va_start (arg_ptr, format); vfprintf (stderr, format, arg_ptr); if (*format && format[strlen(format)-1] != '\n') putc ('\n', stderr); va_end (arg_ptr); } /* Prepend FNAME with the srcdir environment variable's value and * return an allocated filename. */ char * prepend_srcdir (const char *fname) { static const char *srcdir; char *result; if (!srcdir && !(srcdir = getenv ("srcdir"))) srcdir = "."; result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); strcpy (result, srcdir); strcat (result, "/"); strcat (result, fname); return result; } /* Read next line but skip over empty and comment lines. Caller must xfree the result. */ static char * read_textline (FILE *fp, int *lineno) { char line[4096]; char *p; do { if (!fgets (line, sizeof line, fp)) { if (feof (fp)) return NULL; die ("error reading input line: %s\n", strerror (errno)); } ++*lineno; p = strchr (line, '\n'); if (!p) die ("input line %d not terminated or too long\n", *lineno); *p = 0; for (p--;p > line && my_isascii (*p) && isspace (*p); p--) *p = 0; } while (!*line || *line == '#'); /* if (debug) */ /* info ("read line: '%s'\n", line); */ return xstrdup (line); } /* * The input line is like: * * [mod = L=2048, N=256, SHA-384] * */ static void parse_annotation (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '-'); if (!s) { fail ("syntax error at input line %d", lineno); return; } *buffer = xstrdup (s-3); (*buffer)[strlen (*buffer) - 1] = 0; /* Remove ']'. */ } /* Copy the data after the tag to BUFFER. BUFFER will be allocated as needed. */ static void copy_data (char **buffer, const char *line, int lineno) { const char *s; xfree (*buffer); *buffer = NULL; s = strchr (line, '='); if (!s) { fail ("syntax error at input line %d", lineno); return; } for (s++; my_isascii (*s) && isspace (*s); s++) ; *buffer = xstrdup (s); } /* Convert STRING consisting of hex characters into its binary representation and return it as an allocated buffer. The valid length of the buffer is returned at R_LENGTH. The string is delimited by end of string. The function returns NULL on error. */ static void * hex2buffer (const char *string, size_t *r_length) { const char *s; unsigned char *buffer; size_t length; buffer = xmalloc (strlen(string)/2+1); length = 0; for (s=string; *s; s +=2 ) { if (!hexdigitp (s) || !hexdigitp (s+1)) return NULL; /* Invalid hex digits. */ ((unsigned char*)buffer)[length++] = xtoi_2 (s); } *r_length = length; return buffer; } static void one_test_sexp (const char *sha_alg, const char *p, const char *q, const char *g, const char *x, const char *y, const char *msg, const char *k, const char *r, const char *s) { gpg_error_t err; int i; char *p0; void *buffer = NULL; void *buffer2 = NULL; void *buffer3 = NULL; void *buffer4 = NULL; void *buffer5 = NULL; size_t buflen, buflen2, buflen3, buflen4, buflen5; gcry_ctx_t ctx = NULL; int md_algo; const char *data_tmpl; gcry_md_hd_t hd = NULL; gcry_sexp_t s_pk = NULL; gcry_sexp_t s_sk = NULL; gcry_sexp_t s_sig= NULL; gcry_sexp_t s_tmp, s_tmp2; unsigned char *out_r = NULL; unsigned char *out_s = NULL; size_t out_r_len, out_s_len; char *sig_r_string = NULL; char *sig_s_string = NULL; if (verbose > 1) info ("Running test %s\n", sha_alg); if (!strcmp (sha_alg, "SHA-1")) md_algo = GCRY_MD_SHA1; else if (!strcmp (sha_alg, "SHA-224")) md_algo = GCRY_MD_SHA224; else if (!strcmp (sha_alg, "SHA-256")) md_algo = GCRY_MD_SHA256; else if (!strcmp (sha_alg, "SHA-384")) md_algo = GCRY_MD_SHA384; else if (!strcmp (sha_alg, "SHA-512")) md_algo = GCRY_MD_SHA512; else { fail ("error for test, %s: %s: %s", "SHA algo", "invalid", sha_alg); goto leave; } err = gcry_md_open (&hd, md_algo, 0); if (err) { fail ("algo %d, gcry_md_open failed: %s\n", md_algo, gpg_strerror (err)); return; } if (!(buffer = hex2buffer (p, &buflen))) { fail ("error parsing for test, %s: %s", "p", "invalid hex string"); goto leave; } if (!(buffer2 = hex2buffer (q, &buflen2))) { fail ("error parsing for test, %s: %s", "q", "invalid hex string"); goto leave; } if (!(buffer3 = hex2buffer (g, &buflen3))) { fail ("error parsing for test, %s: %s", "g", "invalid hex string"); goto leave; } if (!(buffer4 = hex2buffer (y, &buflen4))) { fail ("error parsing for test, %s: %s", "y", "invalid hex string"); goto leave; } if (!(buffer5 = hex2buffer (x, &buflen5))) { fail ("error parsing for test, %s: %s", "x", "invalid hex string"); goto leave; } err = gcry_sexp_build (&s_sk, NULL, "(private-key (dsa (p %b)(q %b)(g %b)(y %b)(x %b)))", (int)buflen, buffer, (int)buflen2, buffer2, (int)buflen3, buffer3, (int)buflen4, buffer4, (int)buflen5, buffer5); if (err) { fail ("error building SEXP for test, %s: %s", "sk", gpg_strerror (err)); goto leave; } err = gcry_sexp_build (&s_pk, NULL, "(public-key (dsa (p %b)(q %b)(g %b)(y %b)))", (int)buflen, buffer, (int)buflen2, buffer2, (int)buflen3, buffer3, (int)buflen4, buffer4); if (err) { fail ("error building SEXP for test, %s: %s", "pk", gpg_strerror (err)); goto leave; } xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (buffer4); xfree (buffer5); buffer = buffer2 = buffer3 = buffer4 = buffer5 = NULL; if (!(buffer = hex2buffer (msg, &buflen))) { fail ("error parsing for test, %s: %s", "msg", "invalid hex string"); goto leave; } gcry_md_write (hd, buffer, buflen); xfree (buffer); buffer = NULL; if (!(buffer2 = hex2buffer (k, &buflen2))) { fail ("error parsing for test, %s: %s", "salt_val", "invalid hex string"); goto leave; } err = gcry_pk_random_override_new (&ctx, buffer2, buflen2); if (err) { fail ("error setting salt for test: %s", gpg_strerror (err)); goto leave; } xfree (buffer2); buffer2 = NULL; data_tmpl = "(data(flags raw)(hash %s %b)(label %b))"; err = gcry_pk_hash_sign (&s_sig, data_tmpl, s_sk, hd, ctx); if (err) { - fail ("gcry_pkey_hash_sign failed: %s", gpg_strerror (err)); + if (in_fips_mode) + { + if (verbose) + show_note ("DSA is not allowed in FIPS mode\n"); + } + else + fail ("gcry_pkey_hash_sign failed: %s", gpg_strerror (err)); goto leave; } out_r_len = out_s_len = 0; out_s = out_r = NULL; s_tmp2 = NULL; s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0); if (s_tmp) { s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "dsa", 0); if (s_tmp) { gcry_sexp_release (s_tmp2); s_tmp2 = s_tmp; s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0); if (s_tmp) { const char *p1; size_t n; out_r_len = buflen2; out_r = xmalloc (out_r_len); if (!out_r) { err = gpg_error_from_syserror (); gcry_sexp_release (s_tmp); gcry_sexp_release (s_tmp2); goto leave; } p1 = gcry_sexp_nth_data (s_tmp, 1, &n); if (n == out_r_len) memcpy (out_r, p1, out_r_len); else { memset (out_r, 0, out_r_len - n); memcpy (out_r + out_r_len - n, p1, n); } gcry_sexp_release (s_tmp); } s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0); if (s_tmp) { const char *p1; size_t n; out_s_len = out_r_len; out_s = xmalloc (out_s_len); if (!out_s) { err = gpg_error_from_syserror (); gcry_sexp_release (s_tmp); gcry_sexp_release (s_tmp2); goto leave; } p1 = gcry_sexp_nth_data (s_tmp, 1, &n); if (n == out_s_len) memcpy (out_s, p1, out_s_len); else { memset (out_s, 0, out_s_len - n); memcpy (out_s + out_s_len - n, p1, n); } gcry_sexp_release (s_tmp); } } } gcry_sexp_release (s_tmp2); sig_r_string = xmalloc (2*out_r_len+1); p0 = sig_r_string; *p0 = 0; for (i=0; i < out_r_len; i++, p0 += 2) snprintf (p0, 3, "%02x", out_r[i]); sig_s_string = xmalloc (2*out_s_len+1); p0 = sig_s_string; *p0 = 0; for (i=0; i < out_s_len; i++, p0 += 2) snprintf (p0, 3, "%02x", out_s[i]); if (strcmp (sig_r_string, r) || strcmp (sig_s_string, s)) { fail ("gcry_pk_hash_sign failed: %s", "wrong value returned"); info (" expected: '%s'", r); info (" got: '%s'", sig_r_string); info (" expected: '%s'", s); info (" got: '%s'", sig_s_string); } if (!no_verify) { err = gcry_pk_hash_verify (s_sig, data_tmpl, s_pk, hd, ctx); if (err) fail ("gcry_pk_hash_verify failed for test: %s", gpg_strerror (err)); } leave: gcry_ctx_release (ctx); gcry_sexp_release (s_sig); gcry_sexp_release (s_sk); gcry_sexp_release (s_pk); if (hd) gcry_md_close (hd); xfree (buffer); xfree (buffer2); xfree (buffer3); xfree (buffer4); xfree (buffer5); xfree (out_r); xfree (out_s); xfree (sig_r_string); xfree (sig_s_string); } static void check_dsa (const char *fname) { FILE *fp; int lineno, ntests; char *line; char *sha_alg; char *p, *q, *g; char *msg, *x, *y, *k, *r, *s; info ("Checking DSA.\n"); fp = fopen (fname, "r"); if (!fp) die ("error opening '%s': %s\n", fname, strerror (errno)); sha_alg = NULL; p = q = g = NULL; msg = x = y = k = r = s = NULL; lineno = ntests = 0; while ((line = read_textline (fp, &lineno))) { if (!strncmp (line, "[mod", 4)) parse_annotation (&sha_alg, line, lineno); else if (!strncmp (line, "P =", 3)) copy_data (&p, line, lineno); else if (!strncmp (line, "Q =", 3)) copy_data (&q, line, lineno); else if (!strncmp (line, "G =", 3)) copy_data (&g, line, lineno); else if (!strncmp (line, "Msg =", 5)) copy_data (&msg, line, lineno); else if (!strncmp (line, "X =", 3)) copy_data (&x, line, lineno); else if (!strncmp (line, "Y =", 3)) copy_data (&y, line, lineno); else if (!strncmp (line, "K =", 3)) copy_data (&k, line, lineno); else if (!strncmp (line, "R =", 3)) copy_data (&r, line, lineno); else if (!strncmp (line, "S =", 3)) copy_data (&s, line, lineno); else fail ("unknown tag at input line %d", lineno); xfree (line); if (sha_alg && p && q && g && msg && x && y && k && r && s) { one_test_sexp (sha_alg, p, q, g, x, y, msg, k, r, s); ntests++; if (!(ntests % 256)) show_note ("%d of %d tests done\n", ntests, N_TESTS); xfree (msg); msg = NULL; xfree (x); x = NULL; xfree (y); y = NULL; xfree (k); k = NULL; xfree (r); r = NULL; xfree (s); s = NULL; } } xfree (p); xfree (q); xfree (g); xfree (sha_alg); xfree (msg); xfree (x); xfree (y); xfree (k); xfree (r); xfree (s); if (ntests != N_TESTS && !custom_data_file) fail ("did %d tests but expected %d", ntests, N_TESTS); else if ((ntests % 256)) show_note ("%d tests done\n", ntests); fclose (fp); } int main (int argc, char **argv) { int last_argc = -1; char *fname = NULL; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --no-verify skip the verify test\n" " --data FNAME take test data from file FNAME\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--no-verify")) { no_verify = 1; argc--; argv++; } else if (!strcmp (*argv, "--data")) { argc--; argv++; if (argc) { xfree (fname); fname = xstrdup (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (!fname) fname = prepend_srcdir ("t-dsa.inp"); else custom_data_file = 1; xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); if (gcry_fips_mode_active ()) in_fips_mode = 1; start_timer (); check_dsa (fname); stop_timer (); xfree (fname); info ("All tests completed in %s. Errors: %d\n", elapsed_time (1), error_count); return !!error_count; }