unsigned pubkey_to_bits(gnutls_pk_algorithm_t pk, gnutls_pk_params_st * params) { switch (pk) { case GNUTLS_PK_RSA: return _gnutls_mpi_get_nbits(params->params[RSA_MODULUS]); case GNUTLS_PK_DSA: return _gnutls_mpi_get_nbits(params->params[DSA_P]); case GNUTLS_PK_EC: return gnutls_ecc_curve_get_size(params->flags) * 8; default: return 0; } }
/** * cdk_pk_get_nbits: * @pk: the public key * * Return the length of the public key in bits. * The meaning of length is actually the size of the 'prime' * object in the key. For RSA keys the modulus, for ElG/DSA * the size of the public prime. **/ int cdk_pk_get_nbits (cdk_pubkey_t pk) { if (!pk || !pk->mpi[0]) return 0; return _gnutls_mpi_get_nbits (pk->mpi[0]); }
/* You can use a NULL buf to get the output size only */ static cdk_error_t mpi_to_buffer (bigint_t a, byte * buf, size_t buflen, size_t * r_nwritten, size_t * r_nbits) { size_t nbits; int err; if (!a || !r_nwritten) { gnutls_assert (); return CDK_Inv_Value; } nbits = _gnutls_mpi_get_nbits (a); if (r_nbits) *r_nbits = nbits; if (r_nwritten) *r_nwritten = (nbits + 7) / 8 + 2; if ((nbits + 7) / 8 + 2 > buflen) return CDK_Too_Short; *r_nwritten = buflen; err = _gnutls_mpi_print (a, buf, r_nwritten); if (err < 0) { gnutls_assert (); return map_gnutls_error (err); } return 0; }
/* A = g^a % N * returns A and a (which is random) */ bigint_t _gnutls_calc_srp_A (bigint_t * a, bigint_t g, bigint_t n) { bigint_t tmpa; bigint_t A; int bits; bits = _gnutls_mpi_get_nbits (n); tmpa = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM); A = _gnutls_mpi_new (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_dh_params_export_raw - export the raw DH parameters * @params: Holds the DH parameters * @prime: will hold the new prime * @generator: will hold the new generator * @bits: if non null will hold is the prime's number of bits * * This function will export the pair of prime and generator for use * in the Diffie-Hellman key exchange. The new parameters will be * allocated using gnutls_malloc() and will be stored in the * appropriate datum. * * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned, * otherwise an error code is returned. **/ int gnutls_dh_params_export_raw (gnutls_dh_params_t params, gnutls_datum_t * prime, gnutls_datum_t * generator, unsigned int *bits) { int ret; if (params->params[1] == NULL || params->params[0] == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_mpi_dprint (params->params[1], generator); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_mpi_dprint (params->params[0], prime); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (generator); return ret; } if (bits) *bits = _gnutls_mpi_get_nbits (params->params[0]); return 0; }
/* 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_privkey_get_pk_algorithm: * @key: should contain a #gnutls_privkey_t type * @bits: If set will return the number of bits of the parameters (may be NULL) * * This function will return the public key algorithm of a private * key and if possible will return a number of bits that indicates * the security parameter of the key. * * Returns: a member of the #gnutls_pk_algorithm_t enumeration on * success, or a negative error code on error. * * Since: 2.12.0 **/ int gnutls_privkey_get_pk_algorithm(gnutls_privkey_t key, unsigned int *bits) { switch (key->type) { #ifdef ENABLE_OPENPGP case GNUTLS_PRIVKEY_OPENPGP: return gnutls_openpgp_privkey_get_pk_algorithm(key->key.openpgp, bits); #endif #ifdef ENABLE_PKCS11 case GNUTLS_PRIVKEY_PKCS11: return gnutls_pkcs11_privkey_get_pk_algorithm(key->key.pkcs11, bits); #endif case GNUTLS_PRIVKEY_X509: if (bits) *bits = _gnutls_mpi_get_nbits(key->key.x509-> params.params[0]); return gnutls_x509_privkey_get_pk_algorithm(key->key.x509); case GNUTLS_PRIVKEY_EXT: if (bits) *bits = 0; return key->pk_algorithm; default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } }
/** * gnutls_dh_params_import_dsa: * @dh_params: The parameters * @key: holds a DSA private key * * This function will import the prime and generator of the DSA key for use * in the Diffie-Hellman key exchange. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_dh_params_import_dsa(gnutls_dh_params_t dh_params, gnutls_x509_privkey_t key) { gnutls_datum_t p, g, q; bigint_t tmp_q; int ret; ret = gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, NULL, NULL); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_mpi_init_scan_nz(&tmp_q, q.data, q.size); if (ret < 0) { gnutls_assert(); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } ret = gnutls_dh_params_import_raw2(dh_params, &p, &g, _gnutls_mpi_get_nbits(tmp_q)); _gnutls_mpi_release(&tmp_q); cleanup: gnutls_free(p.data); gnutls_free(g.data); gnutls_free(q.data); return ret; }
/* This function reads the RSA parameters from the private key */ static int _gnutls_get_private_rsa_params (gnutls_session_t session, bigint_t ** params, int *params_size) { int bits; gnutls_certificate_credentials_t cred; gnutls_rsa_params_t rsa_params; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.selected_cert_list == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } bits = _gnutls_mpi_get_nbits (session->internals.selected_cert_list[0]. params[0]); if (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters.current_cipher_suite) == GNUTLS_KX_RSA_EXPORT && bits > 512) { rsa_params = _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func, session); /* EXPORT case: */ if (rsa_params == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } /* In the export case, we do use temporary RSA params * of 512 bits size. The params in the certificate are * used to sign this temporary stuff. */ *params_size = RSA_PRIVATE_PARAMS; *params = rsa_params->params; return 0; } /* non export cipher suites. */ *params_size = session->internals.selected_key->params_size; *params = session->internals.selected_key->params; return 0; }
int _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session, gnutls_buffer_st * data, gnutls_datum_t * pskkey) { int ret; gnutls_pk_params_st peer_pub; gnutls_datum_t tmp_dh_key = {NULL, 0}; gnutls_pk_params_init(&peer_pub); ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0, &session->key.dh_params, 1); if (ret < 0) return gnutls_assert_val(ret); _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X])); ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0); if (ret < 0) { gnutls_assert(); goto error; } peer_pub.params[DH_Y] = session->key.client_Y; /* calculate the key after calculating the message */ ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_cipher_suite_get_kx_algo (session->security_parameters.cipher_suite) != GNUTLS_KX_DHE_PSK) { session->key.key.data = tmp_dh_key.data; session->key.key.size = tmp_dh_key.size; } else { /* In DHE_PSK the key is set differently */ ret = _gnutls_set_psk_session_key(session, pskkey, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { gnutls_assert(); goto error; } ret = data->length; error: gnutls_pk_params_clear(&session->key.dh_params); return ret; }
int _gnutls_ecc_ansi_x963_export(gnutls_ecc_curve_t curve, bigint_t x, bigint_t y, gnutls_datum_t * out) { int numlen = gnutls_ecc_curve_get_size(curve); int byte_size, ret; size_t size; if (numlen == 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); out->size = 1 + 2 * numlen; out->data = gnutls_malloc(out->size); if (out->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); memset(out->data, 0, out->size); /* store byte 0x04 */ out->data[0] = 0x04; /* pad and store x */ byte_size = (_gnutls_mpi_get_nbits(x) + 7) / 8; size = out->size - (1 + (numlen - byte_size)); ret = _gnutls_mpi_print(x, &out->data[1 + (numlen - byte_size)], &size); if (ret < 0) return gnutls_assert_val(ret); byte_size = (_gnutls_mpi_get_nbits(y) + 7) / 8; size = out->size - (1 + (numlen + numlen - byte_size)); ret = _gnutls_mpi_print(y, &out->data[1 + numlen + numlen - byte_size], &size); if (ret < 0) return gnutls_assert_val(ret); /* pad and store y */ return 0; }
static size_t calc_mpisize (bigint_t mpi[MAX_CDK_PK_PARTS], size_t ncount) { size_t size, i; size = 0; for (i = 0; i < ncount; i++) size += (_gnutls_mpi_get_nbits (mpi[i]) + 7) / 8 + 2; return size; }
/* returns the public value (X), and the secret (ret_x). */ mpi_t gnutls_calc_dh_secret (mpi_t * ret_x, mpi_t g, mpi_t prime) { mpi_t e, x; int x_size = _gnutls_mpi_get_nbits (prime) - 1; /* The size of the secret key is less than * prime/2 */ if (x_size > MAX_BITS || x_size <= 0) { gnutls_assert (); return NULL; } x = _gnutls_mpi_new (x_size); if (x == NULL) { gnutls_assert (); if (ret_x) *ret_x = NULL; return NULL; } /* FIXME: (x_size/8)*8 is there to overcome a bug in libgcrypt * which does not really check the bits given but the bytes. */ do { _gnutls_mpi_randomize (x, (x_size / 8) * 8, GCRY_STRONG_RANDOM); /* Check whether x is zero. */ } while (_gnutls_mpi_cmp_ui (x, 0) == 0); e = _gnutls_mpi_alloc_like (prime); if (e == NULL) { gnutls_assert (); if (ret_x) *ret_x = NULL; _gnutls_mpi_release (&x); return NULL; } _gnutls_mpi_powm (e, g, x, prime); if (ret_x) *ret_x = x; else _gnutls_mpi_release (&x); return e; }
/* returns the blinded c and the inverse of a random * number r; */ static bigint_t rsa_blind (bigint_t c, bigint_t e, bigint_t n, bigint_t * _ri) { bigint_t nc = NULL, r = NULL, ri = NULL; /* nc = c*(r^e) * ri = r^(-1) */ nc = _gnutls_mpi_alloc_like (n); if (nc == NULL) { gnutls_assert (); return NULL; } ri = _gnutls_mpi_alloc_like (n); if (nc == NULL) { gnutls_assert (); goto fail; } r = _gnutls_mpi_randomize (NULL, _gnutls_mpi_get_nbits (n), GNUTLS_RND_NONCE); if (r == NULL) { gnutls_assert (); goto fail; } /* invert r */ if (mpz_invert (ri, r, n) == 0) { gnutls_assert (); goto fail; } /* r = r^e */ _gnutls_mpi_powm (r, r, e, n); _gnutls_mpi_mulm (nc, c, r, n); *_ri = ri; _gnutls_mpi_release (&r); return nc; fail: _gnutls_mpi_release (&nc); _gnutls_mpi_release (&r); return NULL; }
/** * gnutls_x509_privkey_sec_param: * @key: a key structure * * This function will return the security parameter appropriate with * this private key. * * Returns: On success, a valid security parameter is returned otherwise * %GNUTLS_SEC_PARAM_UNKNOWN is returned. **/ gnutls_sec_param_t gnutls_x509_privkey_sec_param (gnutls_x509_privkey_t key) { int ret; switch (key->pk_algorithm) { case GNUTLS_PK_RSA: ret = gnutls_pk_bits_to_sec_param (GNUTLS_PK_RSA, _gnutls_mpi_get_nbits (key->params[0] /*m */ )); break; case GNUTLS_PK_DSA: ret = gnutls_pk_bits_to_sec_param (GNUTLS_PK_DSA, _gnutls_mpi_get_nbits (key->params[0] /*p */ )); break; default: ret = GNUTLS_SEC_PARAM_UNKNOWN; } return ret; }
static int wrap_gcry_pk_fixup (gnutls_pk_algorithm_t algo, gnutls_direction_t direction, gnutls_pk_params_st * params) { int ret, result; /* only for RSA we invert the coefficient --pgp type */ if (algo != GNUTLS_PK_RSA) return 0; if (params->params[5] == NULL) params->params[5] = _gnutls_mpi_new (_gnutls_mpi_get_nbits (params->params[0])); if (params->params[5] == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = 1; if (direction == GNUTLS_IMPORT) { /* calculate exp1 [6] and exp2 [7] */ _gnutls_mpi_release (¶ms->params[6]); _gnutls_mpi_release (¶ms->params[7]); result = _gnutls_calc_rsa_exp (params->params, RSA_PRIVATE_PARAMS); if (result < 0) { gnutls_assert (); return result; } ret = gcry_mpi_invm (params->params[5], params->params[3], params->params[4]); params->params_nr = RSA_PRIVATE_PARAMS; } else if (direction == GNUTLS_EXPORT) ret = gcry_mpi_invm (params->params[5], params->params[4], params->params[3]); if (ret == 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } return 0; }
/* * Copyright (C) 2007-2012 Free Software Foundation, Inc. * * Author: Nikos Mavrogiannopoulos, Simon Josefsson * * This file is part of GnuTLS. * * GnuTLS is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuTLS 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GnuTLS; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include "utils.h" #include "../lib/gnutls_int.h" #include "../lib/gnutls_mpi.h" #include "../lib/gnutls_errors.h" #include "../lib/debug.h" static void tls_log_func (int level, const char *str) { fprintf (stderr, "|<%d>| %s", level, str); } #define RND_BITS 510 /* not multiple of 8 */ void doit (void) { int rc; bigint_t n1, n2, n3, n4; gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); if (debug) gnutls_global_set_log_level (99); n1 = _gnutls_mpi_new (1000); if (n1 == NULL) fail ("mpi_new failed\n"); n2 = _gnutls_mpi_set_ui (NULL, 2); if (n2 == NULL) fail ("mpi_set_ui failed\n"); n3 = _gnutls_mpi_set_ui (NULL, 5); if (n3 == NULL) fail ("mpi_set_ui failed\n"); _gnutls_mpi_randomize (n1, RND_BITS, GNUTLS_RND_NONCE); _gnutls_mpi_log ("rand:", n1); rc = _gnutls_mpi_get_nbits (n1); if (rc > RND_BITS) fail ("mpi_get_nbits failed... returned %d\n", rc); n4 = _gnutls_mpi_addm (NULL, n1, n3, n2); if (n4 == NULL) fail ("mpi_set_ui failed\n"); if (_gnutls_mpi_cmp_ui (n4, 0) != 0 && _gnutls_mpi_cmp_ui (n4, 1) != 0) fail ("mpi_cmp_ui failed\n"); _gnutls_mpi_release (&n1); _gnutls_mpi_release (&n2); _gnutls_mpi_release (&n3); _gnutls_mpi_release (&n4); gnutls_global_deinit (); if (debug) success ("mpi ops ok\n"); }
static int mpi_buf2bits(gnutls_datum_t * mpi_buf) { bigint_t mpi; int rc; rc = _gnutls_mpi_init_scan_nz(&mpi, mpi_buf->data, mpi_buf->size); if (rc) { gnutls_assert(); return rc; } rc = _gnutls_mpi_get_nbits(mpi); _gnutls_mpi_release(&mpi); return rc; }
int _gnutls_dh_common_print_server_kx (gnutls_session_t session, bigint_t g, bigint_t p, unsigned int q_bits, gnutls_buffer_st* data) { bigint_t x, Y; int ret; /* Y=g^x mod p */ ret = gnutls_calc_dh_secret (&Y, &x, g, p, q_bits); if (ret < 0) { gnutls_assert (); return ret; } session->key.dh_secret = x; _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x)); ret = _gnutls_buffer_append_mpi(data, 16, p, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_mpi(data, 16, g, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_mpi(data, 16, Y, 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = data->length; cleanup: _gnutls_mpi_release (&Y); return ret; }
int _gnutls_dh_common_print_server_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret; unsigned q_bits = session->key.dh_params.flags; if (q_bits < 192 && q_bits != 0) { gnutls_assert(); _gnutls_debug_log("too small q_bits value for DH: %u\n", q_bits); q_bits = 0; /* auto-detect */ } /* Y=g^x mod p */ ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, q_bits, &session->key.dh_params, 1); if (ret < 0) return gnutls_assert_val(ret); _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X])); ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_P], 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_G], 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = data->length; cleanup: return ret; }
gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (bigint_t q) { int bits = _gnutls_mpi_get_nbits (q); if (bits <= 160) { return GNUTLS_DIG_SHA1; } else if (bits <= 224) { return GNUTLS_DIG_SHA224; } else { return GNUTLS_DIG_SHA256; } }
static int write_mpi (cdk_stream_t out, bigint_t m) { byte buf[MAX_MPI_BYTES + 2]; size_t nbits, nread; int err; if (!out || !m) return CDK_Inv_Value; nbits = _gnutls_mpi_get_nbits (m); if (nbits > MAX_MPI_BITS || nbits < 1) return CDK_MPI_Error; nread = MAX_MPI_BYTES + 2; err = _gnutls_mpi_print_pgp (m, buf, &nread); if (err < 0) return map_gnutls_error (err); return stream_write (out, buf, nread); }
mpi_t gnutls_calc_dh_key (mpi_t f, mpi_t x, mpi_t prime) { mpi_t k; int bits; bits = _gnutls_mpi_get_nbits (prime); if (bits <= 0 || bits > MAX_BITS) { gnutls_assert (); return NULL; } k = _gnutls_mpi_alloc_like (prime); if (k == NULL) return NULL; _gnutls_mpi_powm (k, f, x, prime); return k; }
/** * gnutls_dh_params_generate2: * @dparams: The parameters * @bits: is the prime's number of bits * * This function will generate a new pair of prime and generator for use in * the Diffie-Hellman key exchange. This may take long time. * * It is recommended not to set the number of bits directly, but * use gnutls_sec_param_to_pk_bits() instead. * Also note that the DH parameters are only useful to servers. * Since clients use the parameters sent by the server, it's of * no use to call this in client side. * * The parameters generated are of the DSA form. It also is possible * to generate provable parameters (following the Shawe-Taylor * algorithm), using gnutls_x509_privkey_generate2() with DSA option * and the %GNUTLS_PRIVKEY_FLAG_PROVABLE flag set. These can the * be imported with gnutls_dh_params_import_dsa(). * * It is no longer recommended for applications to generate parameters. * See the "Parameter generation" section in the manual. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_dh_params_generate2(gnutls_dh_params_t dparams, unsigned int bits) { int ret; gnutls_pk_params_st params; gnutls_pk_params_init(¶ms); ret = _gnutls_pk_generate_params(GNUTLS_PK_DH, bits, ¶ms); if (ret < 0) return gnutls_assert_val(ret); dparams->params[0] = params.params[DSA_P]; dparams->params[1] = params.params[DSA_G]; dparams->q_bits = _gnutls_mpi_get_nbits(params.params[DSA_Q]); _gnutls_mpi_release(¶ms.params[DSA_Q]); return 0; }
gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash (bigint_t q, unsigned int* hash_len) { int bits = _gnutls_mpi_get_nbits (q); if (bits <= 160) { if (hash_len) *hash_len = 20; return GNUTLS_DIG_SHA1; } else if (bits <= 224) { if (hash_len) *hash_len = 28; return GNUTLS_DIG_SHA256; } else { if (hash_len) *hash_len = 32; return GNUTLS_DIG_SHA256; } }
/* if the peer's certificate is of 512 bits or less, returns non zero. */ int _gnutls_peers_cert_less_512 (gnutls_session_t session) { gnutls_cert peer_cert; int ret; cert_auth_info_t 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 0; } if ((ret = _gnutls_get_auth_info_gcert (&peer_cert, session->security_parameters.cert_type, info, CERT_NO_COPY)) < 0) { gnutls_assert (); return 0; } if (peer_cert.subject_pk_algorithm != GNUTLS_PK_RSA) { gnutls_assert (); _gnutls_gcert_deinit (&peer_cert); return 0; } if (_gnutls_mpi_get_nbits (peer_cert.params[0]) <= 512) { _gnutls_gcert_deinit (&peer_cert); return 1; } _gnutls_gcert_deinit (&peer_cert); return 0; }
/** * gnutls_rsa_params_export_raw - This function will export the RSA parameters * @params: 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 * @bits: if non null will hold the prime's number of bits * * This function will export the RSA 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_rsa_params_export_raw (gnutls_rsa_params_t params, gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u, unsigned int *bits) { int ret; ret = gnutls_x509_privkey_export_rsa_raw (params, m, e, d, p, q, u); if (ret < 0) { gnutls_assert (); return ret; } if (bits) *bits = _gnutls_mpi_get_nbits (params->params[3]); return 0; }
/* Hash an entire public key PK with the given message digest context MD. The @usefpr param is only valid for version 3 keys because of the different way to calculate the fingerprint. */ cdk_error_t _cdk_hash_pubkey (cdk_pubkey_t pk, digest_hd_st * md, int usefpr) { byte buf[12]; size_t i, n, npkey; if (!pk || !md) return CDK_Inv_Value; if (usefpr && pk->version < 4 && is_RSA (pk->pubkey_algo)) return hash_mpibuf (pk, md, 1); /* The version 4 public key packet does not have the 2 octets for the expiration date. */ n = pk->version < 4 ? 8 : 6; npkey = cdk_pk_get_npkey (pk->pubkey_algo); for (i = 0; i < npkey; i++) n = n + (_gnutls_mpi_get_nbits (pk->mpi[i]) + 7) / 8 + 2; i = 0; buf[i++] = 0x99; buf[i++] = n >> 8; buf[i++] = n >> 0; buf[i++] = pk->version; buf[i++] = pk->timestamp >> 24; buf[i++] = pk->timestamp >> 16; buf[i++] = pk->timestamp >> 8; buf[i++] = pk->timestamp >> 0; if (pk->version < 4) { u16 a = 0; /* Convert the expiration date into days. */ if (pk->expiredate) a = (u16) ((pk->expiredate - pk->timestamp) / 86400L); buf[i++] = a >> 8; buf[i++] = a; }
/* 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; }
/* 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; }