static int wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st * params) { int ret; switch (algo) { case GNUTLS_PK_RSA: case GNUTLS_PK_DSA: return 0; case GNUTLS_PK_EC: { /* just verify that x and y lie on the curve */ struct ecc_point r, pub; const struct ecc_curve *curve; if (params->params_nr != ECC_PUBLIC_PARAMS) return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); curve = get_supported_curve(params->flags); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _ecc_params_to_pubkey(params, &pub, curve); if (ret < 0) return gnutls_assert_val(ret); ecc_point_init(&r, curve); /* verify that x,y lie on the curve */ ret = ecc_point_set(&r, TOMPZ(params->params[ECC_X]), TOMPZ(params->params[ECC_Y])); if (ret == 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } ecc_point_clear(&r); ret = 0; ecc_cleanup: ecc_point_clear(&pub); } break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } return ret; }
static int _ecc_params_to_pubkey(const gnutls_pk_params_st * pk_params, struct ecc_point *pub, const struct ecc_curve *curve) { ecc_point_init(pub, curve); if (ecc_point_set (pub, pk_params->params[ECC_X], pk_params->params[ECC_Y]) == 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); return 0; }
static void ecc_shared_secret(struct ecc_scalar *private_key, struct ecc_point *public_key, void *out, unsigned size) { struct ecc_point r; mpz_t x; mpz_init(x); ecc_point_init(&r, public_key->ecc); ecc_point_mul(&r, private_key, public_key); ecc_point_get(&r, x, NULL); nettle_mpz_get_str_256(size, out, x); mpz_clear(x); ecc_point_clear(&r); return; }
static void * bench_ecdsa_init (unsigned size) { struct ecdsa_ctx *ctx; const struct ecc_curve *ecc; const char *xs; const char *ys; const char *zs; mpz_t x, y, z; ctx = xalloc (sizeof(*ctx)); dsa_signature_init (&ctx->s); knuth_lfib_init (&ctx->rctx, 17); switch (size) { case 192: ecc = &_nettle_secp_192r1; xs = "8e8e07360350fb6b7ad8370cfd32fa8c6bba785e6e200599"; ys = "7f82ddb58a43d59ff8dc66053002b918b99bd01bd68d6736"; zs = "f2e620e086d658b4b507996988480917640e4dc107808bdd"; ctx->digest = hash_string (&nettle_sha1, "abc"); ctx->digest_size = 20; break; case 224: ecc = &_nettle_secp_224r1; xs = "993bf363f4f2bc0f255f22563980449164e9c894d9efd088d7b77334"; ys = "b75fff9849997d02d135140e4d0030944589586e22df1fc4b629082a"; zs = "cdfd01838247f5de3cc70b688418046f10a2bfaca6de9ec836d48c27"; ctx->digest = hash_string (&nettle_sha224, "abc"); ctx->digest_size = 28; break; /* From RFC 4754 */ case 256: ecc = &_nettle_secp_256r1; xs = "2442A5CC 0ECD015F A3CA31DC 8E2BBC70 BF42D60C BCA20085 E0822CB0 4235E970"; ys = "6FC98BD7 E50211A4 A27102FA 3549DF79 EBCB4BF2 46B80945 CDDFE7D5 09BBFD7D"; zs = "DC51D386 6A15BACD E33D96F9 92FCA99D A7E6EF09 34E70975 59C27F16 14C88A7F"; ctx->digest = hash_string (&nettle_sha256, "abc"); ctx->digest_size = 32; break; case 384: ecc = &_nettle_secp_384r1; xs = "96281BF8 DD5E0525 CA049C04 8D345D30 82968D10 FEDF5C5A CA0C64E6 465A97EA" "5CE10C9D FEC21797 41571072 1F437922"; ys = "447688BA 94708EB6 E2E4D59F 6AB6D7ED FF9301D2 49FE49C3 3096655F 5D502FAD" "3D383B91 C5E7EDAA 2B714CC9 9D5743CA"; zs = "0BEB6466 34BA8773 5D77AE48 09A0EBEA 865535DE 4C1E1DCB 692E8470 8E81A5AF" "62E528C3 8B2A81B3 5309668D 73524D9F"; ctx->digest = hash_string (&nettle_sha384, "abc"); ctx->digest_size = 48; break; case 521: ecc = &_nettle_secp_521r1; xs = "0151518F 1AF0F563 517EDD54 85190DF9 5A4BF57B 5CBA4CF2 A9A3F647 4725A35F" "7AFE0A6D DEB8BEDB CD6A197E 592D4018 8901CECD 650699C9 B5E456AE A5ADD190" "52A8"; ys = "006F3B14 2EA1BFFF 7E2837AD 44C9E4FF 6D2D34C7 3184BBAD 90026DD5 E6E85317" "D9DF45CA D7803C6C 20035B2F 3FF63AFF 4E1BA64D 1C077577 DA3F4286 C58F0AEA" "E643"; zs = "0065FDA3 409451DC AB0A0EAD 45495112 A3D813C1 7BFD34BD F8C1209D 7DF58491" "20597779 060A7FF9 D704ADF7 8B570FFA D6F062E9 5C7E0C5D 5481C5B1 53B48B37" "5FA1"; ctx->digest = hash_string (&nettle_sha512, "abc"); ctx->digest_size = 64; break; default: die ("Internal error.\n"); } ecc_point_init (&ctx->pub, ecc); ecc_scalar_init (&ctx->key, ecc); mpz_init_set_str (x, xs, 16); mpz_init_set_str (y, ys, 16); mpz_init_set_str (z, zs, 16); ecc_point_set (&ctx->pub, x, y); ecc_scalar_set (&ctx->key, z); mpz_clear (x); mpz_clear (y); mpz_clear (z); ecdsa_sign (&ctx->key, &ctx->rctx, (nettle_random_func *) knuth_lfib_random, ctx->digest_size, ctx->digest, &ctx->s); return ctx; }
void test_main (void) { unsigned i; struct knuth_lfib_ctx rctx; struct dsa_signature signature; struct tstring *digest; knuth_lfib_init (&rctx, 4711); dsa_signature_init (&signature); digest = SHEX (/* sha256("abc") */ "BA7816BF 8F01CFEA 414140DE 5DAE2223" "B00361A3 96177A9C B410FF61 F20015AD"); for (i = 0; ecc_curves[i]; i++) { const struct ecc_curve *ecc = ecc_curves[i]; struct ecc_point pub; struct ecc_scalar key; if (verbose) fprintf (stderr, "Curve %d\n", ecc->bit_size); ecc_point_init (&pub, ecc); ecc_scalar_init (&key, ecc); ecdsa_generate_keypair (&pub, &key, &rctx, (nettle_random_func *) knuth_lfib_random); if (verbose) { gmp_fprintf (stderr, "Public key:\nx = %Nx\ny = %Nx\n", pub.p, ecc->size, pub.p + ecc->size, ecc->size); gmp_fprintf (stderr, "Private key: %Nx\n", key.p, ecc->size); } if (!ecc_valid_p (&pub)) die ("ecdsa_generate_keypair produced an invalid point.\n"); ecdsa_sign (&key, &rctx, (nettle_random_func *) knuth_lfib_random, digest->length, digest->data, &signature); if (!ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify failed.\n"); digest->data[3] ^= 17; if (ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify returned success with invalid digest.\n"); digest->data[3] ^= 17; mpz_combit (signature.r, 117); if (ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify returned success with invalid signature.r.\n"); mpz_combit (signature.r, 117); mpz_combit (signature.s, 93); if (ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify returned success with invalid signature.s.\n"); ecc_point_clear (&pub); ecc_scalar_clear (&key); } dsa_signature_clear (&signature); }
static int wrap_nettle_pk_verify_params(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st * params) { int ret; switch (algo) { case GNUTLS_PK_RSA: { bigint_t t1 = NULL, t2 = NULL; if (params->params_nr != RSA_PRIVATE_PARAMS) return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); t1 = _gnutls_mpi_new(256); if (t1 == NULL) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _gnutls_mpi_mulm(t1, params->params[RSA_PRIME1], params->params[RSA_PRIME2], params->params[RSA_MODULUS]); if (_gnutls_mpi_cmp_ui(t1, 0) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } mpz_invert(TOMPZ(t1), TOMPZ(params->params[RSA_PRIME2]), TOMPZ(params->params[RSA_PRIME1])); if (_gnutls_mpi_cmp(t1, params->params[RSA_COEF]) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } /* [RSA_PRIME1] = d % p-1, [RSA_PRIME2] = d % q-1 */ _gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME1], 1); t2 = _gnutls_mpi_mod(params->params[RSA_PRIV], t1); if (t2 == NULL) { ret = gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); goto rsa_cleanup; } if (_gnutls_mpi_cmp(params->params[RSA_E1], t2) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } _gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME2], 1); _gnutls_mpi_release(&t2); t2 = _gnutls_mpi_mod(params->params[RSA_PRIV], t1); if (t2 == NULL) { ret = gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); goto rsa_cleanup; } if (_gnutls_mpi_cmp(params->params[RSA_E2], t2) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } ret = 0; rsa_cleanup: _gnutls_mpi_release(&t1); _gnutls_mpi_release(&t2); } break; case GNUTLS_PK_DSA: { bigint_t t1 = NULL; if (params->params_nr != DSA_PRIVATE_PARAMS) return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); t1 = _gnutls_mpi_new(256); if (t1 == NULL) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _gnutls_mpi_powm(t1, params->params[DSA_G], params->params[DSA_X], params->params[DSA_P]); if (_gnutls_mpi_cmp(t1, params->params[DSA_Y]) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto dsa_cleanup; } ret = 0; dsa_cleanup: _gnutls_mpi_release(&t1); } break; case GNUTLS_PK_EC: { struct ecc_point r, pub; struct ecc_scalar priv; mpz_t x1, y1, x2, y2; const struct ecc_curve *curve; if (params->params_nr != ECC_PRIVATE_PARAMS) return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); curve = get_supported_curve(params->flags); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _ecc_params_to_pubkey(params, &pub, curve); if (ret < 0) return gnutls_assert_val(ret); ret = _ecc_params_to_privkey(params, &priv, curve); if (ret < 0) { ecc_point_clear(&pub); return gnutls_assert_val(ret); } ecc_point_init(&r, curve); /* verify that x,y lie on the curve */ ret = ecc_point_set(&r, TOMPZ(params->params[ECC_X]), TOMPZ(params->params[ECC_Y])); if (ret == 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } ecc_point_clear(&r); ecc_point_init(&r, curve); ecc_point_mul_g(&r, &priv); mpz_init(x1); mpz_init(y1); ecc_point_get(&r, x1, y1); ecc_point_clear(&r); mpz_init(x2); mpz_init(y2); ecc_point_get(&pub, x2, y2); /* verify that k*(Gx,Gy)=(x,y) */ if (mpz_cmp(x1, x2) != 0 || mpz_cmp(y1, y2) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } ret = 0; ecc_cleanup: ecc_scalar_clear(&priv); ecc_point_clear(&pub); } break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } return ret; }
static int wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, unsigned int level /*bits */ , gnutls_pk_params_st * params) { int ret; unsigned int i, q_bits; memset(params, 0, sizeof(*params)); switch (algo) { case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_private_key priv; dsa_public_key_init(&pub); dsa_private_key_init(&priv); /* the best would be to use _gnutls_pk_bits_to_subgroup_bits() * but we do NIST DSA here */ if (level <= 1024) q_bits = 160; else q_bits = 256; ret = dsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level, q_bits); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; goto dsa_fail; } params->params_nr = 0; for (i = 0; i < DSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like(&pub.p); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto dsa_fail; } params->params_nr++; } ret = 0; _gnutls_mpi_set(params->params[0], pub.p); _gnutls_mpi_set(params->params[1], pub.q); _gnutls_mpi_set(params->params[2], pub.g); _gnutls_mpi_set(params->params[3], pub.y); _gnutls_mpi_set(params->params[4], priv.x); dsa_fail: dsa_private_key_clear(&priv); dsa_public_key_clear(&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_RSA: { struct rsa_public_key pub; struct rsa_private_key priv; rsa_public_key_init(&pub); rsa_private_key_init(&priv); _gnutls_mpi_set_ui(&pub.e, 65537); ret = rsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level, 0); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; goto rsa_fail; } params->params_nr = 0; for (i = 0; i < RSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like(&pub.n); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto rsa_fail; } params->params_nr++; } ret = 0; _gnutls_mpi_set(params->params[0], pub.n); _gnutls_mpi_set(params->params[1], pub.e); _gnutls_mpi_set(params->params[2], priv.d); _gnutls_mpi_set(params->params[3], priv.p); _gnutls_mpi_set(params->params[4], priv.q); _gnutls_mpi_set(params->params[5], priv.c); _gnutls_mpi_set(params->params[6], priv.a); _gnutls_mpi_set(params->params[7], priv.b); rsa_fail: rsa_private_key_clear(&priv); rsa_public_key_clear(&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_EC: { struct ecc_scalar key; struct ecc_point pub; const struct ecc_curve *curve; curve = get_supported_curve(level); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ecc_scalar_init(&key, curve); ecc_point_init(&pub, curve); ecdsa_generate_keypair(&pub, &key, NULL, rnd_func); params->params[ECC_X] = _gnutls_mpi_new(0); params->params[ECC_Y] = _gnutls_mpi_new(0); params->params[ECC_K] = _gnutls_mpi_new(0); if (params->params[ECC_X] == NULL || params->params[ECC_Y] == NULL || params->params[ECC_K] == NULL) { _gnutls_mpi_release(¶ms-> params[ECC_X]); _gnutls_mpi_release(¶ms-> params[ECC_Y]); _gnutls_mpi_release(¶ms-> params[ECC_K]); goto ecc_cleanup; } params->flags = level; params->params_nr = ECC_PRIVATE_PARAMS; ecc_point_get(&pub, TOMPZ(params->params[ECC_X]), TOMPZ(params->params[ECC_Y])); ecc_scalar_get(&key, TOMPZ(params->params[ECC_K])); ecc_cleanup: ecc_point_clear(&pub); ecc_scalar_clear(&key); break; } default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } return 0; fail: for (i = 0; i < params->params_nr; i++) { _gnutls_mpi_release(¶ms->params[i]); } params->params_nr = 0; return ret; }
/* To generate a DH key either q must be set in the params or * level should be set to the number of required bits. */ static int wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, unsigned int level /*bits */ , gnutls_pk_params_st * params) { int ret; unsigned int i; switch (algo) { case GNUTLS_PK_DSA: #ifdef ENABLE_FIPS140 { struct dsa_public_key pub; struct dsa_private_key priv; if (params->params[DSA_Q] == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); _dsa_params_to_pubkey(params, &pub); dsa_private_key_init(&priv); mpz_init(pub.y); ret = dsa_generate_dss_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto dsa_fail; } ret = _gnutls_mpi_init_multi(¶ms->params[DSA_Y], ¶ms->params[DSA_X], NULL); if (ret < 0) { gnutls_assert(); goto dsa_fail; } mpz_set(TOMPZ(params->params[DSA_Y]), pub.y); mpz_set(TOMPZ(params->params[DSA_X]), priv.x); params->params_nr += 2; dsa_fail: dsa_private_key_clear(&priv); mpz_clear(pub.y); if (ret < 0) goto fail; break; } #endif case GNUTLS_PK_DH: { struct dsa_public_key pub; mpz_t r; mpz_t x, y; int max_tries; unsigned have_q = 0; if (algo != params->algo) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); _dsa_params_to_pubkey(params, &pub); if (params->params[DSA_Q] != NULL) have_q = 1; /* This check is for the case !ENABLE_FIPS140 */ if (algo == GNUTLS_PK_DSA && have_q == 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); mpz_init(r); mpz_init(x); mpz_init(y); max_tries = 3; do { if (have_q) { mpz_set(r, pub.q); mpz_sub_ui(r, r, 2); nettle_mpz_random(x, NULL, rnd_func, r); mpz_add_ui(x, x, 1); } else { unsigned size = mpz_sizeinbase(pub.p, 2); if (level == 0) level = MIN(size, DH_EXPONENT_SIZE(size)); nettle_mpz_random_size(x, NULL, rnd_func, level); if (level >= size) mpz_mod(x, x, pub.p); } mpz_powm(y, pub.g, x, pub.p); max_tries--; if (max_tries <= 0) { gnutls_assert(); ret = GNUTLS_E_RANDOM_FAILED; goto dh_fail; } } while(mpz_cmp_ui(y, 1) == 0); ret = _gnutls_mpi_init_multi(¶ms->params[DSA_Y], ¶ms->params[DSA_X], NULL); if (ret < 0) { gnutls_assert(); goto dh_fail; } mpz_set(TOMPZ(params->params[DSA_Y]), y); mpz_set(TOMPZ(params->params[DSA_X]), x); params->params_nr += 2; ret = 0; dh_fail: mpz_clear(r); mpz_clear(x); mpz_clear(y); if (ret < 0) goto fail; break; } case GNUTLS_PK_RSA: { struct rsa_public_key pub; struct rsa_private_key priv; rsa_public_key_init(&pub); rsa_private_key_init(&priv); mpz_set_ui(pub.e, 65537); #ifdef ENABLE_FIPS140 ret = rsa_generate_fips186_4_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level); #else ret = rsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level, 0); #endif if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto rsa_fail; } params->params_nr = 0; for (i = 0; i < RSA_PRIVATE_PARAMS; i++) { ret = _gnutls_mpi_init(¶ms->params[i]); if (ret < 0) { gnutls_assert(); goto rsa_fail; } params->params_nr++; } mpz_set(TOMPZ(params->params[0]), pub.n); mpz_set(TOMPZ(params->params[1]), pub.e); mpz_set(TOMPZ(params->params[2]), priv.d); mpz_set(TOMPZ(params->params[3]), priv.p); mpz_set(TOMPZ(params->params[4]), priv.q); mpz_set(TOMPZ(params->params[5]), priv.c); mpz_set(TOMPZ(params->params[6]), priv.a); mpz_set(TOMPZ(params->params[7]), priv.b); ret = 0; rsa_fail: rsa_private_key_clear(&priv); rsa_public_key_clear(&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_EC: { struct ecc_scalar key; struct ecc_point pub; const struct ecc_curve *curve; curve = get_supported_curve(level); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ecc_scalar_init(&key, curve); ecc_point_init(&pub, curve); ecdsa_generate_keypair(&pub, &key, NULL, rnd_func); ret = _gnutls_mpi_init_multi(¶ms->params[ECC_X], ¶ms->params[ECC_Y], ¶ms->params[ECC_K], NULL); if (ret < 0) { gnutls_assert(); goto ecc_fail; } params->flags = level; params->params_nr = ECC_PRIVATE_PARAMS; ecc_point_get(&pub, TOMPZ(params->params[ECC_X]), TOMPZ(params->params[ECC_Y])); ecc_scalar_get(&key, TOMPZ(params->params[ECC_K])); ret = 0; ecc_fail: ecc_point_clear(&pub); ecc_scalar_clear(&key); if (ret < 0) goto fail; break; } default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } FAIL_IF_LIB_ERROR; return 0; fail: for (i = 0; i < params->params_nr; i++) { _gnutls_mpi_release(¶ms->params[i]); } params->params_nr = 0; FAIL_IF_LIB_ERROR; return ret; }