int _gnutls_calc_rsa_exp (bigint_t * params, unsigned int params_size) { bigint_t tmp = _gnutls_mpi_alloc_like (params[0]); if (params_size < RSA_PRIVATE_PARAMS - 2) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if (tmp == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* [6] = d % p-1, [7] = d % q-1 */ _gnutls_mpi_sub_ui (tmp, params[3], 1); params[6] = _gnutls_mpi_mod (params[2] /*d */ , tmp); _gnutls_mpi_sub_ui (tmp, params[4], 1); params[7] = _gnutls_mpi_mod (params[2] /*d */ , tmp); _gnutls_mpi_release (&tmp); if (params[7] == NULL || params[6] == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
/* Checks if b%n==0 which is a fatal srp error. * Returns a proper error code in that case, and 0 when * all are ok. */ inline static int check_b_mod_n (mpi_t b, mpi_t n) { int ret; mpi_t r = _gnutls_mpi_alloc_like (b); if (r == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_mod (r, b, n); ret = _gnutls_mpi_cmp_ui (r, 0); _gnutls_mpi_release (&r); if (ret == 0) { gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } return 0; }
/* Checks if a%n==0,+1,-1%n which is a fatal srp error. * Returns a proper error code in that case, and 0 when * all are ok. */ inline static int check_a_mod_n (bigint_t a, bigint_t n) { int ret; bigint_t r; r = _gnutls_mpi_mod (a, n); if (r == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = _gnutls_mpi_cmp_ui (r, 0); _gnutls_mpi_release (&r); if (ret == 0) { gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } return 0; }
/* Encodes the RSA parameters into an ASN.1 RSA private key structure. */ static int _encode_rsa (ASN1_TYPE * c2, mpi_t * params) { int result, i; size_t size[8], total; opaque *m_data, *pube_data, *prie_data; opaque *p1_data, *p2_data, *u_data, *exp1_data, *exp2_data; opaque *all_data = NULL, *p; mpi_t exp1 = NULL, exp2 = NULL, q1 = NULL, p1 = NULL, u = NULL; opaque null = '\0'; /* Read all the sizes */ total = 0; for (i = 0; i < 5; i++) { _gnutls_mpi_print_lz (NULL, &size[i], params[i]); total += size[i]; } /* Now generate exp1 and exp2 */ exp1 = _gnutls_mpi_salloc_like (params[0]); /* like modulus */ if (exp1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } exp2 = _gnutls_mpi_salloc_like (params[0]); if (exp2 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } q1 = _gnutls_mpi_salloc_like (params[4]); if (q1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p1 = _gnutls_mpi_salloc_like (params[3]); if (p1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } u = _gnutls_mpi_salloc_like (params[3]); if (u == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } _gnutls_mpi_invm (u, params[4], params[3]); /* inverse of q mod p */ _gnutls_mpi_print_lz (NULL, &size[5], u); total += size[5]; _gnutls_mpi_sub_ui (p1, params[3], 1); _gnutls_mpi_sub_ui (q1, params[4], 1); _gnutls_mpi_mod (exp1, params[2], p1); _gnutls_mpi_mod (exp2, params[2], q1); /* calculate exp's size */ _gnutls_mpi_print_lz (NULL, &size[6], exp1); total += size[6]; _gnutls_mpi_print_lz (NULL, &size[7], exp2); total += size[7]; /* Encoding phase. * allocate data enough to hold everything */ all_data = gnutls_secure_malloc (total); if (all_data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p = all_data; m_data = p; p += size[0]; pube_data = p; p += size[1]; prie_data = p; p += size[2]; p1_data = p; p += size[3]; p2_data = p; p += size[4]; u_data = p; p += size[5]; exp1_data = p; p += size[6]; exp2_data = p; _gnutls_mpi_print_lz (m_data, &size[0], params[0]); _gnutls_mpi_print_lz (pube_data, &size[1], params[1]); _gnutls_mpi_print_lz (prie_data, &size[2], params[2]); _gnutls_mpi_print_lz (p1_data, &size[3], params[3]); _gnutls_mpi_print_lz (p2_data, &size[4], params[4]); _gnutls_mpi_print_lz (u_data, &size[5], u); _gnutls_mpi_print_lz (exp1_data, &size[6], exp1); _gnutls_mpi_print_lz (exp2_data, &size[7], exp2); /* Ok. Now we have the data. Create the asn1 structures */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Write PRIME */ if ((result = asn1_write_value (*c2, "modulus", m_data, size[0])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "publicExponent", pube_data, size[1])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "privateExponent", prie_data, size[2])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "prime1", p1_data, size[3])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "prime2", p2_data, size[4])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "exponent1", exp1_data, size[6])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "exponent2", exp2_data, size[7])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "coefficient", u_data, size[5])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } _gnutls_mpi_release (&exp1); _gnutls_mpi_release (&exp2); _gnutls_mpi_release (&q1); _gnutls_mpi_release (&p1); _gnutls_mpi_release (&u); gnutls_free (all_data); if ((result = asn1_write_value (*c2, "otherPrimeInfos", NULL, 0)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } return 0; cleanup: _gnutls_mpi_release (&u); _gnutls_mpi_release (&exp1); _gnutls_mpi_release (&exp2); _gnutls_mpi_release (&q1); _gnutls_mpi_release (&p1); asn1_delete_structure (c2); gnutls_free (all_data); return result; }
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: { int curve = params->flags; ecc_key ecc_priv; ecc_point *R; ecc_point zero; if (params->params_nr != ECC_PRIVATE_PARAMS) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); if (is_supported_curve(curve) == 0) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); _ecc_params_to_privkey(params, &ecc_priv); R = ecc_new_point(); /* verify that x,y lie on the curve */ ret = ecc_projective_check_point(&ecc_priv.pubkey, TOMPZ(params->params[ECC_B]), params->params[ECC_PRIME]); if (ret != 0) { ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } memcpy(&zero.x, ecc_priv.Gx, sizeof(mpz_t)); memcpy(&zero.y, ecc_priv.Gy, sizeof(mpz_t)); memcpy(&zero.z, ecc_priv.pubkey.z, sizeof(mpz_t)); /* z = 1 */ /* verify that k*(Gx,Gy)=(x,y) */ ret = ecc_mulmod_cached(ecc_priv.k, curve, R, TOMPZ(params->params[ECC_A]), TOMPZ(params->params[ECC_PRIME]), 1); if (ret != 0) { ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } if (mpz_cmp(ecc_priv.pubkey.x, R->x) != 0 || mpz_cmp(ecc_priv.pubkey.y, R->y) != 0) { ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } ret = 0; ecc_cleanup: _ecc_params_clear(&ecc_priv); ecc_del_point(R); } break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } return ret; }
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; }