/** * gnutls_dh_params_import_raw - import DH parameters * @dh_params: Is a structure that will hold the prime numbers * @prime: holds the new prime * @generator: holds the new generator * * This function will replace the pair of prime and generator for use * in the Diffie-Hellman key exchange. The new parameters should be * stored in the appropriate gnutls_datum. * * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned, * otherwise an error code is returned. **/ int gnutls_dh_params_import_raw (gnutls_dh_params_t dh_params, const gnutls_datum_t * prime, const gnutls_datum_t * generator) { bigint_t tmp_prime, tmp_g; size_t siz; siz = prime->size; if (_gnutls_mpi_scan_nz (&tmp_prime, prime->data, siz)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } siz = generator->size; if (_gnutls_mpi_scan_nz (&tmp_g, generator->data, siz)) { _gnutls_mpi_release (&tmp_prime); gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* store the generated values */ dh_params->params[0] = tmp_prime; dh_params->params[1] = tmp_g; return 0; }
/** * gnutls_x509_privkey_import_ecc_raw: * @key: The structure to store the parsed key * @curve: holds the curve * @x: holds the x * @y: holds the y * @k: holds the k * * This function will convert the given elliptic curve parameters to the * native #gnutls_x509_privkey_t format. The output will be stored * in @key. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.0 **/ int gnutls_x509_privkey_import_ecc_raw (gnutls_x509_privkey_t key, gnutls_ecc_curve_t curve, const gnutls_datum_t * x, const gnutls_datum_t * y, const gnutls_datum_t * k) { int ret; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } key->params.flags = curve; ret = _gnutls_ecc_curve_fill_params(curve, &key->params); if (ret < 0) return gnutls_assert_val(ret); if (_gnutls_mpi_scan_nz (&key->params.params[ECC_X], x->data, x->size)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; if (_gnutls_mpi_scan_nz (&key->params.params[ECC_Y], y->data, y->size)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; if (_gnutls_mpi_scan_nz (&key->params.params[ECC_K], k->data, k->size)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; key->pk_algorithm = GNUTLS_PK_EC; return 0; cleanup: gnutls_pk_params_release(&key->params); return ret; }
static int read_rs(bigint_t *r, bigint_t *s, uint8_t *data, size_t data_size) { unsigned int dhalf = data_size/2; if (_gnutls_mpi_scan_nz (r, data, dhalf) != 0) return gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); if (_gnutls_mpi_scan_nz (s, &data[dhalf], dhalf) != 0) { _gnutls_mpi_release(r); return gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); } return 0; }
/** * gnutls_srp_verifier - Used to calculate an SRP verifier * @username: is the user's name * @password: is the user's password * @salt: should be some randomly generated bytes * @generator: is the generator of the group * @prime: is the group's prime * @res: where the verifier will be stored. * * This function will create an SRP verifier, as specified in RFC2945. * The @prime and @generator should be one of the static parameters defined * in gnutls/extra.h or may be generated using the GCRYPT functions * gcry_prime_generate() and gcry_prime_group_generator(). * The verifier will be allocated with @malloc and will be stored in @res using * binary format. * **/ int gnutls_srp_verifier (const char *username, const char *password, const gnutls_datum_t * salt, const gnutls_datum_t * generator, const gnutls_datum_t * prime, gnutls_datum_t * res) { mpi_t _n, _g; int ret; size_t digest_size = 20, size; opaque digest[20]; ret = _gnutls_calc_srp_sha (username, password, salt->data, salt->size, &digest_size, digest); if (ret < 0) { gnutls_assert (); return ret; } size = prime->size; if (_gnutls_mpi_scan_nz (&_n, prime->data, &size)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } size = generator->size; if (_gnutls_mpi_scan_nz (&_g, generator->data, &size)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } ret = _gnutls_srp_gx (digest, 20, &res->data, _g, _n, malloc); if (ret < 0) { gnutls_assert (); return ret; } res->size = ret; return 0; }
/* This calculates the SHA1(A | B) * A and B will be left-padded with zeros to fill n_size. */ mpi_t _gnutls_calc_srp_u (mpi_t A, mpi_t B, mpi_t n) { size_t b_size, a_size; opaque *holder, hd[MAX_HASH_SIZE]; size_t holder_size, hash_size, n_size; GNUTLS_HASH_HANDLE td; int ret; mpi_t res; /* get the size of n in bytes */ _gnutls_mpi_print (NULL, &n_size, n); _gnutls_mpi_print (NULL, &a_size, A); _gnutls_mpi_print (NULL, &b_size, B); if (a_size > n_size || b_size > n_size) { gnutls_assert (); return NULL; /* internal error */ } holder_size = n_size + n_size; holder = gnutls_calloc (1, holder_size); if (holder == NULL) return NULL; _gnutls_mpi_print (&holder[n_size - a_size], &a_size, A); _gnutls_mpi_print (&holder[n_size + n_size - b_size], &b_size, B); td = _gnutls_hash_init (GNUTLS_MAC_SHA1); if (td == NULL) { gnutls_free (holder); gnutls_assert (); return NULL; } _gnutls_hash (td, holder, holder_size); _gnutls_hash_deinit (td, hd); /* convert the bytes of hd to integer */ hash_size = 20; /* SHA */ ret = _gnutls_mpi_scan_nz (&res, hd, &hash_size); gnutls_free (holder); if (ret < 0) { gnutls_assert (); return NULL; } return res; }
int _gnutls_srp_gx (opaque * text, size_t textsize, opaque ** result, bigint_t g, bigint_t prime, gnutls_alloc_function galloc_func) { bigint_t x, e; size_t result_size; int ret; if (_gnutls_mpi_scan_nz (&x, text, textsize)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } e = _gnutls_mpi_alloc_like (prime); if (e == NULL) { gnutls_assert (); _gnutls_mpi_release (&x); return GNUTLS_E_MEMORY_ERROR; } /* e = g^x mod prime (n) */ _gnutls_mpi_powm (e, g, x, prime); _gnutls_mpi_release (&x); ret = _gnutls_mpi_print (e, NULL, &result_size); if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { *result = galloc_func (result_size); if ((*result) == NULL) return GNUTLS_E_MEMORY_ERROR; _gnutls_mpi_print (e, *result, &result_size); ret = result_size; } else { gnutls_assert (); ret = GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_mpi_release (&e); return ret; }
static int _wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, const gnutls_pk_params_st * pk_params) { int ret; switch (algo) { case GNUTLS_PK_RSA: { bigint_t p; if (_gnutls_mpi_scan_nz (&p, plaintext->data, plaintext->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } mpz_powm (p, p, TOMPZ (pk_params->params[1]) /*e */ , TOMPZ (pk_params->params[0] /*m */ )); ret = _gnutls_mpi_dprint_size (p, ciphertext, plaintext->size); _gnutls_mpi_release (&p); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }
/* params is p, q, g, y in that order */ int _gnutls_dsa_verify (const gnutls_datum_t * vdata, const gnutls_datum_t * sig_value, mpi_t * params, int params_len) { mpi_t mdata; int ret; size_t k; mpi_t rs[2]; if (vdata->size != 20) { /* sha-1 only */ gnutls_assert (); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } if (decode_ber_rs (sig_value, &rs[0], &rs[1]) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } k = vdata->size; if (_gnutls_mpi_scan_nz (&mdata, vdata->data, &k) != 0) { gnutls_assert (); _gnutls_mpi_release (&rs[0]); _gnutls_mpi_release (&rs[1]); return GNUTLS_E_MPI_SCAN_FAILED; } /* decrypt signature */ ret = _gnutls_pk_verify (GCRY_PK_DSA, mdata, rs, params, params_len); _gnutls_mpi_release (&mdata); _gnutls_mpi_release (&rs[0]); _gnutls_mpi_release (&rs[1]); if (ret < 0) { gnutls_assert (); return ret; } return 0; /* ok */ }
/* Do DSA signature calculation. params is p, q, g, y, x in that order. */ int _gnutls_dsa_sign (gnutls_datum_t * signature, const gnutls_datum_t * hash, mpi_t * params, unsigned params_len) { mpi_t rs[2], mdata; int ret; size_t k; k = hash->size; if (k != 20) { /* SHA only */ gnutls_assert (); return GNUTLS_E_PK_SIGN_FAILED; } if (_gnutls_mpi_scan_nz (&mdata, hash->data, &k) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } ret = _gnutls_pk_sign (GCRY_PK_DSA, rs, mdata, params, params_len); /* rs[0], rs[1] now hold r,s */ _gnutls_mpi_release (&mdata); if (ret < 0) { gnutls_assert (); return ret; } ret = encode_ber_rs (signature, rs[0], rs[1]); /* free r,s */ _gnutls_mpi_release (&rs[0]); _gnutls_mpi_release (&rs[1]); if (ret != 0) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
int _gnutls_srp_gx (opaque * text, size_t textsize, opaque ** result, mpi_t g, mpi_t prime, gnutls_alloc_function galloc_func) { mpi_t x, e; size_t result_size; if (_gnutls_mpi_scan_nz (&x, text, &textsize)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } e = _gnutls_mpi_alloc_like (prime); if (e == NULL) { gnutls_assert (); _gnutls_mpi_release (&x); return GNUTLS_E_MEMORY_ERROR; } /* e = g^x mod prime (n) */ _gnutls_mpi_powm (e, g, x, prime); _gnutls_mpi_release (&x); _gnutls_mpi_print (NULL, &result_size, e); if (result != NULL) { *result = galloc_func (result_size); if ((*result) == NULL) return GNUTLS_E_MEMORY_ERROR; _gnutls_mpi_print (*result, &result_size, e); } _gnutls_mpi_release (&e); return result_size; }
/* receive the key exchange message ( n, g, s, B) */ int _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data, size_t _data_size) { uint8_t n_s; uint16_t n_g, n_n, n_b; size_t _n_s, _n_g, _n_n, _n_b; const uint8_t *data_n; const uint8_t *data_g; const uint8_t *data_s; const uint8_t *data_b; int i, ret; opaque hd[SRP_MAX_HASH_SIZE]; char *username, *password; ssize_t data_size = _data_size; gnutls_srp_client_credentials_t cred; cred = (gnutls_srp_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.srp_username == NULL) { username = cred->username; password = cred->password; } else { username = session->internals.srp_username; password = session->internals.srp_password; } if (username == NULL || password == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } i = 0; /* Read N */ DECR_LEN (data_size, 2); n_n = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_n); data_n = &data[i]; i += n_n; /* Read G */ DECR_LEN (data_size, 2); n_g = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_g); data_g = &data[i]; i += n_g; /* Read salt */ DECR_LEN (data_size, 1); n_s = data[i]; i += 1; DECR_LEN (data_size, n_s); data_s = &data[i]; i += n_s; /* Read B */ DECR_LEN (data_size, 2); n_b = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_b); data_b = &data[i]; i += n_b; _n_s = n_s; _n_g = n_g; _n_n = n_n; _n_b = n_b; if (_gnutls_mpi_scan_nz (&N, data_n, &_n_n) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&G, data_g, &_n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&B, data_b, &_n_b) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Check if the g and n are from the SRP * draft. Otherwise check if N is a prime and G * a generator. */ if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0) { _gnutls_x509_log ("Checking the SRP group parameters.\n"); if ((ret = group_check_g_n (G, N)) < 0) { gnutls_assert (); return ret; } } /* Checks if b % n == 0 */ if ((ret = check_b_mod_n (B, N)) < 0) { gnutls_assert (); return ret; } /* generate x = SHA(s | SHA(U | ":" | p)) * (or the equivalent using bcrypt) */ if ((ret = _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s, &_n_g, hd)) < 0) { gnutls_assert (); return ret; } if (_gnutls_mpi_scan_nz (&session->key->x, hd, &_n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } return i; /* return the processed data * needed in auth_srp_rsa. */ }
/** * gnutls_x509_privkey_import_dsa_raw - This function will import a raw DSA key * @key: The structure to store the parsed key * @p: holds the p * @q: holds the q * @g: holds the g * @y: holds the y * @x: holds the x * * This function will convert the given DSA raw parameters * to the native gnutls_x509_privkey_t format. The output will be stored in @key. * **/ int gnutls_x509_privkey_import_dsa_raw (gnutls_x509_privkey_t key, const gnutls_datum_t * p, const gnutls_datum_t * q, const gnutls_datum_t * g, const gnutls_datum_t * y, const gnutls_datum_t * x) { int i = 0, ret; size_t siz = 0; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } siz = p->size; if (_gnutls_mpi_scan_nz (&key->params[0], p->data, &siz)) { gnutls_assert (); FREE_DSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = q->size; if (_gnutls_mpi_scan_nz (&key->params[1], q->data, &siz)) { gnutls_assert (); FREE_DSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = g->size; if (_gnutls_mpi_scan_nz (&key->params[2], g->data, &siz)) { gnutls_assert (); FREE_DSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = y->size; if (_gnutls_mpi_scan_nz (&key->params[3], y->data, &siz)) { gnutls_assert (); FREE_DSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } siz = x->size; if (_gnutls_mpi_scan_nz (&key->params[4], x->data, &siz)) { gnutls_assert (); FREE_DSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } if (!key->crippled) { ret = _encode_dsa (&key->key, key->params); if (ret < 0) { gnutls_assert (); FREE_DSA_PRIVATE_PARAMS; return ret; } } key->params_size = DSA_PRIVATE_PARAMS; key->pk_algorithm = GNUTLS_PK_DSA; return 0; }
/* Do PKCS-1 RSA decryption. * params is modulus, public exp., private key * Can decrypt block type 1 and type 2 packets. */ int _gnutls_pkcs1_rsa_decrypt (gnutls_datum_t * plaintext, const gnutls_datum_t * ciphertext, mpi_t * params, unsigned params_len, unsigned btype) { unsigned k, i; int ret; mpi_t c, res; opaque *edata; size_t esize, mod_bits; mod_bits = _gnutls_mpi_get_nbits (params[0]); k = mod_bits / 8; if (mod_bits % 8 != 0) k++; esize = ciphertext->size; if (esize != k) { gnutls_assert (); return GNUTLS_E_PK_DECRYPTION_FAILED; } if (_gnutls_mpi_scan_nz (&c, ciphertext->data, &esize) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* we can use btype to see if the private key is * available. */ if (btype == 2) ret = _gnutls_pk_decrypt (GCRY_PK_RSA, &res, c, params, params_len); else { ret = _gnutls_pk_encrypt (GCRY_PK_RSA, &res, c, params, params_len); } _gnutls_mpi_release (&c); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_mpi_print (NULL, &esize, res); edata = gnutls_alloca (esize + 1); if (edata == NULL) { gnutls_assert (); _gnutls_mpi_release (&res); return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_print (&edata[1], &esize, res); _gnutls_mpi_release (&res); /* EB = 00||BT||PS||00||D * (use block type 'btype') * * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to * avoid attacks similar to the one described by Bleichenbacher in: * "Chosen Ciphertext Attacks against Protocols Based on RSA * Encryption Standard PKCS #1". */ edata[0] = 0; esize++; if (edata[0] != 0 || edata[1] != btype) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_DECRYPTION_FAILED; } ret = GNUTLS_E_DECRYPTION_FAILED; switch (btype) { case 2: for (i = 2; i < esize; i++) { if (edata[i] == 0) { ret = 0; break; } } break; case 1: for (i = 2; i < esize; i++) { if (edata[i] == 0 && i > 2) { ret = 0; break; } if (edata[i] != 0xff) { _gnutls_handshake_log ("PKCS #1 padding error"); /* PKCS #1 padding error. Don't use GNUTLS_E_PKCS1_WRONG_PAD here. */ break; } } break; default: gnutls_assert (); gnutls_afree (edata); break; } i++; if (ret < 0) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_DECRYPTION_FAILED; } if (_gnutls_sset_datum (plaintext, &edata[i], esize - i) < 0) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_MEMORY_ERROR; } gnutls_afree (edata); return 0; }
/** * gnutls_x509_privkey_import_rsa_raw2: * @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. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_import_rsa_raw2 (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, const gnutls_datum_t * e1, const gnutls_datum_t * e2) { int i = 0, ret; size_t siz = 0; gnutls_pk_params_st pk_params; memset (&pk_params, 0, sizeof (pk_params)); if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } key->params_size = 0; 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; } key->params_size++; 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; } key->params_size++; 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; } key->params_size++; 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; } key->params_size++; 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; } key->params_size++; 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; } key->params_size++; if (e1 && e2) { siz = e1->size; if (_gnutls_mpi_scan_nz (&key->params[6], e1->data, siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } key->params_size++; siz = e2->size; if (_gnutls_mpi_scan_nz (&key->params[7], e2->data, siz)) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return GNUTLS_E_MPI_SCAN_FAILED; } key->params_size++; } for (i = 0; i < key->params_size; i++) { pk_params.params[i] = key->params[i]; } pk_params.params_nr = key->params_size; ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &pk_params); if (ret < 0) { gnutls_assert (); FREE_RSA_PRIVATE_PARAMS; return ret; } for (i = 0; i < pk_params.params_nr; i++) { key->params[i] = pk_params.params[i]; } key->params_size = pk_params.params_nr; if (!key->crippled) { ret = _gnutls_asn1_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; }
/** * 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; }
static int _wrap_gcry_pk_verify (gnutls_pk_algorithm_t algo, const gnutls_datum_t * vdata, const gnutls_datum_t * signature, const gnutls_pk_params_st * pk_params) { gcry_sexp_t s_sig = NULL, s_hash = NULL, s_pkey = NULL; int rc = -1, ret; bigint_t hash; bigint_t tmp[2] = { NULL, NULL }; if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_DSA: if (pk_params->params_nr >= 4) rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", pk_params->params[0], pk_params->params[1], pk_params->params[2], pk_params->params[3]); break; case GNUTLS_PK_RSA: if (pk_params->params_nr >= 2) rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", pk_params->params[0], pk_params->params[1]); break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* put the data into a simple list */ if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } switch (algo) { case GNUTLS_PK_DSA: ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(dsa(r%m)(s%m)))", tmp[0], tmp[1]); _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); break; case GNUTLS_PK_RSA: ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size); if (ret < 0) { gnutls_assert (); goto cleanup; } rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(rsa(s%m)))", tmp[0]); _gnutls_mpi_release (&tmp[0]); break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } rc = gcry_pk_verify (s_sig, s_hash, s_pkey); if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; goto cleanup; } ret = 0; cleanup: _gnutls_mpi_release (&hash); if (s_sig) gcry_sexp_release (s_sig); if (s_hash) gcry_sexp_release (s_hash); if (s_pkey) gcry_sexp_release (s_pkey); return ret; }
static int _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, const gnutls_datum_t * vdata, const gnutls_datum_t * signature, const gnutls_pk_params_st * pk_params) { int ret; unsigned int hash_len; bigint_t tmp[2] = { NULL, NULL }; switch (algo) { case GNUTLS_PK_EC: /* ECDSA */ { ecc_key pub; struct dsa_signature sig; int stat; ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } _ecc_params_to_pubkey(pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub); if (ret != 0 || stat != 1) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); _ecc_params_clear( &pub); break; } case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_signature sig; ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } memset(&pub, 0, sizeof(pub)); _dsa_params_to_pubkey (pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = _dsa_verify (&pub, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); break; } case GNUTLS_PK_RSA: { bigint_t hash; if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _int_rsa_verify (pk_params, hash, tmp[0]); _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&hash); break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } cleanup: return ret; }
/* Do PKCS-1 RSA encryption. * params is modulus, public exp. */ int _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, mpi_t * params, unsigned params_len, unsigned btype) { unsigned int i, pad; int ret; mpi_t m, res; opaque *edata, *ps; size_t k, psize; size_t mod_bits; mod_bits = _gnutls_mpi_get_nbits (params[0]); k = mod_bits / 8; if (mod_bits % 8 != 0) k++; if (plaintext->size > k - 11) { gnutls_assert (); return GNUTLS_E_PK_ENCRYPTION_FAILED; } edata = gnutls_alloca (k); if (edata == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* EB = 00||BT||PS||00||D * (use block type 'btype') */ edata[0] = 0; edata[1] = btype; psize = k - 3 - plaintext->size; ps = &edata[2]; switch (btype) { case 2: /* using public key */ if (params_len < RSA_PUBLIC_PARAMS) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } if (gc_pseudo_random (ps, psize) != GC_OK) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_RANDOM_FAILED; } for (i = 0; i < psize; i++) while (ps[i] == 0) { if (gc_pseudo_random (&ps[i], 1) != GC_OK) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_RANDOM_FAILED; } } break; case 1: /* using private key */ if (params_len < RSA_PRIVATE_PARAMS) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } for (i = 0; i < psize; i++) ps[i] = 0xff; break; default: gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } ps[psize] = 0; memcpy (&ps[psize + 1], plaintext->data, plaintext->size); if (_gnutls_mpi_scan_nz (&m, edata, &k) != 0) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_MPI_SCAN_FAILED; } gnutls_afree (edata); if (btype == 2) /* encrypt */ ret = _gnutls_pk_encrypt (GCRY_PK_RSA, &res, m, params, params_len); else /* sign */ ret = _gnutls_pk_sign (GCRY_PK_RSA, &res, m, params, params_len); _gnutls_mpi_release (&m); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_mpi_print (NULL, &psize, res); if (psize < k) { /* padding psize */ pad = k - psize; psize = k; } else if (psize == k) { pad = 0; } else { /* psize > k !!! */ /* This is an impossible situation */ gnutls_assert (); _gnutls_mpi_release (&res); return GNUTLS_E_INTERNAL_ERROR; } ciphertext->data = gnutls_malloc (psize); if (ciphertext->data == NULL) { gnutls_assert (); _gnutls_mpi_release (&res); return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_print (&ciphertext->data[pad], &psize, res); for (i = 0; i < pad; i++) ciphertext->data[i] = 0; ciphertext->size = k; _gnutls_mpi_release (&res); return 0; }
/** * gnutls_x509_privkey_import_dsa_raw: * @key: The structure to store the parsed key * @p: holds the p * @q: holds the q * @g: holds the g * @y: holds the y * @x: holds the x * * This function will convert the given DSA raw parameters to the * native #gnutls_x509_privkey_t format. The output will be stored * in @key. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_import_dsa_raw (gnutls_x509_privkey_t key, const gnutls_datum_t * p, const gnutls_datum_t * q, const gnutls_datum_t * g, const gnutls_datum_t * y, const gnutls_datum_t * x) { int ret; size_t siz = 0; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } siz = p->size; if (_gnutls_mpi_scan_nz (&key->params.params[0], p->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } siz = q->size; if (_gnutls_mpi_scan_nz (&key->params.params[1], q->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } siz = g->size; if (_gnutls_mpi_scan_nz (&key->params.params[2], g->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } siz = y->size; if (_gnutls_mpi_scan_nz (&key->params.params[3], y->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } siz = x->size; if (_gnutls_mpi_scan_nz (&key->params.params[4], x->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } ret = _gnutls_asn1_encode_privkey (GNUTLS_PK_DSA, &key->key, &key->params); if (ret < 0) { gnutls_assert (); goto cleanup; } key->params.params_nr = DSA_PRIVATE_PARAMS; key->pk_algorithm = GNUTLS_PK_DSA; return 0; cleanup: gnutls_pk_params_release(&key->params); return ret; }
static int _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, const gnutls_datum_t * vdata, const gnutls_datum_t * signature, const gnutls_pk_params_st * pk_params) { int ret; unsigned int hash_len; bigint_t tmp[2] = { NULL, NULL }; switch (algo) { case GNUTLS_PK_EC: /* ECDSA */ { ecc_key pub; struct dsa_signature sig; int stat; int curve_id = pk_params->flags; if (is_supported_curve(curve_id) == 0) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } _ecc_params_to_pubkey(pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub, curve_id); if (ret != 0 || stat != 1) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); _ecc_params_clear( &pub); break; } case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_signature sig; ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } memset(&pub, 0, sizeof(pub)); _dsa_params_to_pubkey (pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = _dsa_verify (&pub, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); break; } case GNUTLS_PK_RSA: { struct rsa_public_key pub; _rsa_params_to_pubkey (pk_params, &pub); ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = rsa_pkcs1_verify (&pub, vdata->size, vdata->data, TOMPZ(tmp[0])); if (ret == 0) ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); else ret = 0; _gnutls_mpi_release (&tmp[0]); break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } cleanup: return ret; }
/* just read A and put it to session */ int _gnutls_proc_srp_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { size_t _n_A; ssize_t data_size = _data_size; int ret; DECR_LEN (data_size, 2); _n_A = _gnutls_read_uint16 (&data[0]); DECR_LEN (data_size, _n_A); if (_gnutls_mpi_scan_nz (&A, &data[2], &_n_A) || A == NULL) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } _gnutls_dump_mpi ("SRP A: ", A); _gnutls_dump_mpi ("SRP B: ", B); /* Checks if A % n == 0. */ if ((ret = check_a_mod_n (A, N)) < 0) { gnutls_assert (); return ret; } /* Start the SRP calculations. * - Calculate u */ session->key->u = _gnutls_calc_srp_u (A, B, N); if (session->key->u == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP U: ", session->key->u); /* S = (A * v^u) ^ b % N */ S = _gnutls_calc_srp_S1 (A, _b, session->key->u, V, N); if (S == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP S: ", S); _gnutls_mpi_release (&A); _gnutls_mpi_release (&_b); _gnutls_mpi_release (&V); _gnutls_mpi_release (&session->key->u); _gnutls_mpi_release (&B); ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY); _gnutls_mpi_release (&S); if (ret < 0) { gnutls_assert (); return ret; } return 0; }
static int _wrap_gcry_pk_decrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * plaintext, const gnutls_datum_t * ciphertext, const gnutls_pk_params_st * pk_params) { gcry_sexp_t s_plain = NULL, s_data = NULL, s_pkey = NULL; int rc = -1; int ret; bigint_t data, res; if (_gnutls_mpi_scan_nz (&data, ciphertext->data, ciphertext->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_RSA: if (pk_params->params_nr >= 6) rc = gcry_sexp_build (&s_pkey, NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", pk_params->params[0], pk_params->params[1], pk_params->params[2], pk_params->params[3], pk_params->params[4], pk_params->params[5]); break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* put the data into a simple list */ if (gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data)) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* pass it to libgcrypt */ rc = gcry_pk_decrypt (&s_plain, s_data, s_pkey); if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_PK_DECRYPTION_FAILED; goto cleanup; } res = gcry_sexp_nth_mpi (s_plain, 0, GCRYMPI_FMT_USG); if (res == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = _gnutls_mpi_dprint_size (res, plaintext, ciphertext->size); _gnutls_mpi_release (&res); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = 0; cleanup: _gnutls_mpi_release (&data); if (s_plain) gcry_sexp_release (s_plain); if (s_data) gcry_sexp_release (s_data); if (s_pkey) gcry_sexp_release (s_pkey); return ret; }
int _gnutls_proc_dh_common_client_kx (gnutls_session_t session, uint8_t * data, size_t _data_size, bigint_t g, bigint_t p, gnutls_datum_t* psk_key) { uint16_t n_Y; size_t _n_Y; int ret; ssize_t data_size = _data_size; DECR_LEN (data_size, 2); n_Y = _gnutls_read_uint16 (&data[0]); _n_Y = n_Y; DECR_LEN (data_size, n_Y); if (_gnutls_mpi_scan_nz (&session->key.client_Y, &data[2], _n_Y)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } _gnutls_dh_set_peer_public (session, session->key.client_Y); ret = gnutls_calc_dh_key (&session->key.KEY, session->key.client_Y, session->key.dh_secret, p); if (ret < 0) return gnutls_assert_val(ret); _gnutls_mpi_release (&session->key.client_Y); _gnutls_mpi_release (&session->key.dh_secret); if (psk_key == NULL) { ret = _gnutls_mpi_dprint (session->key.KEY, &session->key.key); } else /* In DHE_PSK the key is set differently */ { gnutls_datum_t tmp_dh_key; ret = _gnutls_mpi_dprint (session->key.KEY, &tmp_dh_key); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key); _gnutls_free_datum (&tmp_dh_key); } _gnutls_mpi_release (&session->key.KEY); if (ret < 0) { return ret; } return 0; }
/* Returns the bytes parsed */ int _gnutls_proc_dh_common_server_kx (gnutls_session_t session, uint8_t * data, size_t _data_size) { uint16_t n_Y, n_g, n_p; size_t _n_Y, _n_g, _n_p; uint8_t *data_p; uint8_t *data_g; uint8_t *data_Y; int i, bits, ret; ssize_t data_size = _data_size; i = 0; DECR_LEN (data_size, 2); n_p = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_p); data_p = &data[i]; i += n_p; DECR_LEN (data_size, 2); n_g = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_g); data_g = &data[i]; i += n_g; DECR_LEN (data_size, 2); n_Y = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_Y); data_Y = &data[i]; _n_Y = n_Y; _n_g = n_g; _n_p = n_p; if (_gnutls_mpi_scan_nz (&session->key.client_Y, data_Y, _n_Y) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&session->key.client_g, data_g, _n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&session->key.client_p, data_p, _n_p) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } bits = _gnutls_dh_get_allowed_prime_bits (session); if (bits < 0) { gnutls_assert (); return bits; } if (_gnutls_mpi_get_nbits (session->key.client_p) < (size_t) bits) { /* the prime used by the peer is not acceptable */ gnutls_assert (); return GNUTLS_E_DH_PRIME_UNACCEPTABLE; } _gnutls_dh_set_group (session, session->key.client_g, session->key.client_p); _gnutls_dh_set_peer_public (session, session->key.client_Y); ret = n_Y + n_p + n_g + 6; return ret; }
static int proc_rsa_export_server_kx (gnutls_session_t session, opaque * data, size_t _data_size) { uint16_t n_m, n_e; size_t _n_m, _n_e; uint8_t *data_m; uint8_t *data_e; int i, sigsize; gnutls_datum_t vparams, signature; int ret; ssize_t data_size = _data_size; cert_auth_info_t info; gnutls_pcert_st peer_cert; info = _gnutls_get_auth_info (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); /* we need this in order to get peer's certificate */ return GNUTLS_E_INTERNAL_ERROR; } i = 0; DECR_LEN (data_size, 2); n_m = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_m); data_m = &data[i]; i += n_m; DECR_LEN (data_size, 2); n_e = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_e); data_e = &data[i]; i += n_e; _n_e = n_e; _n_m = n_m; if (_gnutls_mpi_scan_nz (&session->key->rsa[0], data_m, _n_m) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&session->key->rsa[1], data_e, _n_e) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } _gnutls_rsa_export_set_pubkey (session, session->key->rsa[1], session->key->rsa[0]); /* VERIFY SIGNATURE */ vparams.size = n_m + n_e + 4; vparams.data = data; DECR_LEN (data_size, 2); sigsize = _gnutls_read_uint16 (&data[vparams.size]); DECR_LEN (data_size, sigsize); signature.data = &data[vparams.size + 2]; signature.size = sigsize; if ((ret = _gnutls_get_auth_info_pcert (&peer_cert, session->security_parameters.cert_type, info)) < 0) { gnutls_assert (); return ret; } ret = _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature, GNUTLS_SIGN_UNKNOWN); gnutls_pcert_deinit (&peer_cert); if (ret < 0) { gnutls_assert (); } return ret; }
static int _wrap_gcry_pk_encrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, const gnutls_pk_params_st * pk_params) { gcry_sexp_t s_ciph = NULL, s_data = NULL, s_pkey = NULL; int rc = -1; int ret; bigint_t data, res; gcry_sexp_t list; if (_gnutls_mpi_scan_nz (&data, plaintext->data, plaintext->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_RSA: if (pk_params->params_nr >= 2) rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", pk_params->params[0], pk_params->params[1]); break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* put the data into a simple list */ if (gcry_sexp_build (&s_data, NULL, "%m", data)) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } /* pass it to libgcrypt */ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_PK_ENCRYPTION_FAILED; goto cleanup; } list = gcry_sexp_find_token (s_ciph, "a", 0); if (list == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } res = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); if (res == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = _gnutls_mpi_dprint_size (res, ciphertext, plaintext->size); _gnutls_mpi_release (&res); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = 0; cleanup: _gnutls_mpi_release (&data); if (s_ciph) gcry_sexp_release (s_ciph); if (s_data) gcry_sexp_release (s_data); if (s_pkey) gcry_sexp_release (s_pkey); return ret; }
/** * gnutls_x509_privkey_import_rsa_raw2: * @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 * @e1: holds e1 = d mod (p-1) * @e2: holds e2 = d mod (q-1) * * This function will convert the given RSA raw parameters to the * native #gnutls_x509_privkey_t format. The output will be stored in * @key. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_import_rsa_raw2 (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, const gnutls_datum_t * e1, const gnutls_datum_t * e2) { int ret; size_t siz = 0; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } gnutls_pk_params_init(&key->params); siz = m->size; if (_gnutls_mpi_scan_nz (&key->params.params[0], m->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = e->size; if (_gnutls_mpi_scan_nz (&key->params.params[1], e->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = d->size; if (_gnutls_mpi_scan_nz (&key->params.params[2], d->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = p->size; if (_gnutls_mpi_scan_nz (&key->params.params[3], p->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = q->size; if (_gnutls_mpi_scan_nz (&key->params.params[4], q->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = u->size; if (_gnutls_mpi_scan_nz (&key->params.params[5], u->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; if (e1 && e2) { siz = e1->size; if (_gnutls_mpi_scan_nz (&key->params.params[6], e1->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = e2->size; if (_gnutls_mpi_scan_nz (&key->params.params[7], e2->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; } ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &key->params); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _gnutls_asn1_encode_privkey (GNUTLS_PK_RSA, &key->key, &key->params); if (ret < 0) { gnutls_assert (); goto cleanup; } key->params.params_nr = RSA_PRIVATE_PARAMS; key->pk_algorithm = GNUTLS_PK_RSA; return 0; cleanup: gnutls_pk_params_release(&key->params); return ret; }
static int _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * plaintext, const gnutls_datum_t * ciphertext, const gnutls_pk_params_st * pk_params) { int ret; plaintext->data = NULL; /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_RSA: { struct rsa_private_key priv; struct rsa_public_key pub; unsigned length; bigint_t c; _rsa_params_to_privkey (pk_params, &priv); _rsa_params_to_pubkey (pk_params, &pub); if (_gnutls_mpi_scan_nz (&c, ciphertext->data, ciphertext->size) != 0) { ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); goto cleanup; } length = pub.size; plaintext->data = gnutls_malloc(length); if (plaintext->data == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto cleanup; } ret = rsa_decrypt_tr(&pub, &priv, NULL, rnd_func, &length, plaintext->data, TOMPZ(c)); _gnutls_mpi_release (&c); plaintext->size = length; if (ret == 0) { ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: if (ret < 0) gnutls_free(plaintext->data); return ret; }
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number * Data is allocated by the caller, and should have data_size size. */ int _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data) { int ret; uint8_t *data_n, *data_s; uint8_t *data_g; char *username; SRP_PWD_ENTRY *pwd_entry; srp_server_auth_info_t info; ssize_t data_size; size_t n_b, tmp_size; char buf[64]; uint8_t *data_b; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, sizeof (srp_server_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); username = info->username; _gnutls_str_cpy (username, MAX_SRP_USERNAME, session->security_parameters.extensions.srp_username); ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry); if (ret < 0) { gnutls_assert (); return ret; } /* copy from pwd_entry to local variables (actually in session) */ tmp_size = pwd_entry->g.size; if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->n.size; if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->v.size; if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Calculate: B = (k*v + g^b) % N */ B = _gnutls_calc_srp_B (&_b, G, N, V); if (B == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if (_gnutls_mpi_print (NULL, &n_b, B) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } /* Allocate size to hold the N, g, s, B */ data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 + pwd_entry->salt.size + 1) + (n_b + 2); (*data) = gnutls_malloc (data_size); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* copy N (mod n) */ data_n = *data; _gnutls_write_datum16 (data_n, pwd_entry->n); /* copy G (generator) to data */ data_g = &data_n[2 + pwd_entry->n.size]; _gnutls_write_datum16 (data_g, pwd_entry->g); /* copy the salt */ data_s = &data_g[2 + pwd_entry->g.size]; _gnutls_write_datum8 (data_s, pwd_entry->salt); /* Copy the B value */ data_b = &data_s[1 + pwd_entry->salt.size]; if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) { gnutls_assert(); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_write_uint16 (n_b, data_b); _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b, _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf))); _gnutls_srp_entry_free (pwd_entry); return data_size; }
/* in case of DSA puts into data, r,s */ static int _wrap_gcry_pk_sign (gnutls_pk_algorithm_t algo, gnutls_datum_t * signature, const gnutls_datum_t * vdata, const gnutls_pk_params_st * pk_params) { gcry_sexp_t s_hash = NULL, s_key = NULL, s_sig = NULL; gcry_sexp_t list = NULL; int rc = -1, ret; bigint_t hash; bigint_t res[2] = { NULL, NULL }; if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_DSA: if (pk_params->params_nr >= 5) rc = gcry_sexp_build (&s_key, NULL, "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", pk_params->params[0], pk_params->params[1], pk_params->params[2], pk_params->params[3], pk_params->params[4]); else { gnutls_assert (); } break; case GNUTLS_PK_RSA: if (pk_params->params_nr >= 6) rc = gcry_sexp_build (&s_key, NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", pk_params->params[0], pk_params->params[1], pk_params->params[2], pk_params->params[3], pk_params->params[4], pk_params->params[5]); else { gnutls_assert (); } break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* put the data into a simple list */ if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* pass it to libgcrypt */ rc = gcry_pk_sign (&s_sig, s_hash, s_key); if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_PK_SIGN_FAILED; goto cleanup; } ret = GNUTLS_E_INTERNAL_ERROR; switch (algo) { case GNUTLS_PK_DSA: { list = gcry_sexp_find_token (s_sig, "r", 0); if (list == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); list = gcry_sexp_find_token (s_sig, "s", 0); if (list == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } res[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); ret = _gnutls_encode_ber_rs (signature, res[0], res[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } } break; case GNUTLS_PK_RSA: { list = gcry_sexp_find_token (s_sig, "s", 0); if (list == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); ret = _gnutls_mpi_dprint (res[0], signature); if (ret < 0) { gnutls_assert (); goto cleanup; } } break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: _gnutls_mpi_release (&hash); if (res[0]) _gnutls_mpi_release (&res[0]); if (res[1]) _gnutls_mpi_release (&res[1]); if (s_sig) gcry_sexp_release (s_sig); if (s_hash) gcry_sexp_release (s_hash); if (s_key) gcry_sexp_release (s_key); return ret; }