/* A = g^a % N * returns A and a (which is random) */ mpi_t _gnutls_calc_srp_A (mpi_t * a, mpi_t g, mpi_t n) { mpi_t tmpa; mpi_t A; int bits; bits = _gnutls_mpi_get_nbits (n); tmpa = _gnutls_mpi_snew (bits); if (tmpa == NULL) { gnutls_assert (); return NULL; } _gnutls_mpi_randomize (tmpa, bits, GCRY_STRONG_RANDOM); A = _gnutls_mpi_snew (bits); if (A == NULL) { gnutls_assert (); _gnutls_mpi_release (&tmpa); return NULL; } _gnutls_mpi_powm (A, g, tmpa, n); if (a != NULL) *a = tmpa; else _gnutls_mpi_release (&tmpa); return A; }
/** * gnutls_x509_privkey_export_rsa_raw - This function will export the RSA private key * @key: a structure that holds the rsa parameters * @m: will hold the modulus * @e: will hold the public exponent * @d: will hold the private exponent * @p: will hold the first prime (p) * @q: will hold the second prime (q) * @u: will hold the coefficient * * This function will export the RSA private key's parameters found in the given * structure. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. * **/ int gnutls_x509_privkey_export_rsa_raw (gnutls_x509_privkey_t key, gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u) { int ret; mpi_t coeff = NULL; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } m->data = e->data = d->data = p->data = q->data = u->data = NULL; m->size = e->size = d->size = p->size = q->size = u->size = 0; ret = _gnutls_mpi_dprint (m, key->params[0]); if (ret < 0) { gnutls_assert (); goto error; } /* E */ ret = _gnutls_mpi_dprint (e, key->params[1]); if (ret < 0) { gnutls_assert (); goto error; } /* D */ ret = _gnutls_mpi_dprint (d, key->params[2]); if (ret < 0) { gnutls_assert (); goto error; } /* P */ ret = _gnutls_mpi_dprint (p, key->params[3]); if (ret < 0) { gnutls_assert (); goto error; } /* Q */ ret = _gnutls_mpi_dprint (q, key->params[4]); if (ret < 0) { gnutls_assert (); goto error; } #ifdef CALC_COEFF coeff = _gnutls_mpi_snew (_gnutls_mpi_get_nbits (key->params[0])); if (coeff == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_mpi_invm (coeff, key->params[4], key->params[3]); ret = _gnutls_mpi_dprint (u, coeff); if (ret < 0) { gnutls_assert (); goto error; } _gnutls_mpi_release (&coeff); #else /* U */ ret = _gnutls_mpi_dprint (u, key->params[5]); if (ret < 0) { gnutls_assert (); goto error; } #endif return 0; error: _gnutls_free_datum (m); _gnutls_free_datum (d); _gnutls_free_datum (e); _gnutls_free_datum (p); _gnutls_free_datum (q); _gnutls_mpi_release (&coeff); return ret; }
/** * gnutls_x509_privkey_import_rsa_raw - This function will import a raw RSA key * @key: The structure to store the parsed key * @m: holds the modulus * @e: holds the public exponent * @d: holds the private exponent * @p: holds the first prime (p) * @q: holds the second prime (q) * @u: holds the coefficient * * This function will convert the given RSA raw parameters * to the native gnutls_x509_privkey_t format. The output will be stored in @key. * **/ int gnutls_x509_privkey_import_rsa_raw (gnutls_x509_privkey_t key, const gnutls_datum_t * m, const gnutls_datum_t * e, const gnutls_datum_t * d, const gnutls_datum_t * p, const gnutls_datum_t * q, const gnutls_datum_t * u) { int i = 0, ret; size_t siz = 0; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } siz = m->size; if (_gnutls_mpi_scan_nz (&key->params[0], m->data, &siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = e->size; if (_gnutls_mpi_scan_nz (&key->params[1], e->data, &siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = d->size; if (_gnutls_mpi_scan_nz (&key->params[2], d->data, &siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = p->size; if (_gnutls_mpi_scan_nz (&key->params[3], p->data, &siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = q->size; if (_gnutls_mpi_scan_nz (&key->params[4], q->data, &siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } #ifdef CALC_COEFF key->params[5] = _gnutls_mpi_snew (_gnutls_mpi_get_nbits (key->params[0])); if (key->params[5] == NULL) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_invm (key->params[5], key->params[3], key->params[4]); #else siz = u->size; if (_gnutls_mpi_scan_nz (&key->params[5], u->data, &siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } #endif if (!key->crippled) { ret = _encode_rsa (&key->key, key->params); if (ret < 0) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return ret; } } key->params_size = RSA_PRIVATE_PARAMS; key->pk_algorithm = GNUTLS_PK_RSA; return 0; }
/* Converts an RSA PKCS#1 key to * an internal structure (gnutls_private_key) */ ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) { int result; ASN1_TYPE pkey_asn; if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", &pkey_asn)) != ASN1_SUCCESS) { gnutls_assert (); return NULL; } if ((sizeof (pkey->params) / sizeof (mpi_t)) < RSA_PRIVATE_PARAMS) { gnutls_assert (); /* internal error. Increase the mpi_ts in params */ return NULL; } result = asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_int (pkey_asn, "modulus", &pkey->params[0])) < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_int (pkey_asn, "publicExponent", &pkey->params[1])) < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_int (pkey_asn, "privateExponent", &pkey->params[2])) < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_int (pkey_asn, "prime1", &pkey->params[3])) < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_int (pkey_asn, "prime2", &pkey->params[4])) < 0) { gnutls_assert (); goto error; } #ifdef CALC_COEFF /* Calculate the coefficient. This is because the gcrypt * library is uses the p,q in the reverse order. */ pkey->params[5] = _gnutls_mpi_snew (_gnutls_mpi_get_nbits (pkey->params[0])); if (pkey->params[5] == NULL) { gnutls_assert (); goto error; } _gnutls_mpi_invm (pkey->params[5], pkey->params[3], pkey->params[4]); /* p, q */ #else if ((result = _gnutls_x509_read_int (pkey_asn, "coefficient", &pkey->params[5])) < 0) { gnutls_assert (); goto error; } #endif pkey->params_size = 6; return pkey_asn; error: asn1_delete_structure (&pkey_asn); _gnutls_mpi_release (&pkey->params[0]); _gnutls_mpi_release (&pkey->params[1]); _gnutls_mpi_release (&pkey->params[2]); _gnutls_mpi_release (&pkey->params[3]); _gnutls_mpi_release (&pkey->params[4]); _gnutls_mpi_release (&pkey->params[5]); return NULL; }
/**************** * Choose a random value b and calculate B = (k* v + g^b) % N. * where k == SHA1(N|g) * Return: B and if ret_b is not NULL b. */ mpi_t _gnutls_calc_srp_B (mpi_t * ret_b, mpi_t g, mpi_t n, mpi_t v) { mpi_t tmpB = NULL, tmpV = NULL; mpi_t b = NULL, B = NULL, k = NULL; int bits; /* calculate: B = (k*v + g^b) % N */ bits = _gnutls_mpi_get_nbits (n); b = _gnutls_mpi_snew (bits); if (b == NULL) { gnutls_assert (); return NULL; } tmpV = _gnutls_mpi_alloc_like (n); if (tmpV == NULL) { gnutls_assert (); goto error; } _gnutls_mpi_randomize (b, bits, GCRY_STRONG_RANDOM); tmpB = _gnutls_mpi_snew (bits); if (tmpB == NULL) { gnutls_assert (); goto error; } B = _gnutls_mpi_snew (bits); if (B == NULL) { gnutls_assert (); goto error; } k = _gnutls_calc_srp_u (n, g, n); if (k == NULL) { gnutls_assert (); goto error; } _gnutls_mpi_mulm (tmpV, k, v, n); _gnutls_mpi_powm (tmpB, g, b, n); _gnutls_mpi_addm (B, tmpV, tmpB, n); _gnutls_mpi_release (&k); _gnutls_mpi_release (&tmpB); _gnutls_mpi_release (&tmpV); if (ret_b) *ret_b = b; else _gnutls_mpi_release (&b); return B; error: _gnutls_mpi_release (&b); _gnutls_mpi_release (&B); _gnutls_mpi_release (&k); _gnutls_mpi_release (&tmpB); _gnutls_mpi_release (&tmpV); return NULL; }