int _gnutls_mpi_dprint (const bigint_t a, gnutls_datum_t * dest) { int ret; opaque *buf = NULL; size_t bytes = 0; if (dest == NULL || a == NULL) return GNUTLS_E_INVALID_REQUEST; _gnutls_mpi_print (a, NULL, &bytes); if (bytes != 0) buf = gnutls_malloc (bytes); if (buf == NULL) return GNUTLS_E_MEMORY_ERROR; ret = _gnutls_mpi_print (a, buf, &bytes); if (ret < 0) { gnutls_free (buf); return ret; } dest->data = buf; dest->size = bytes; 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; }
/* Writes the specified integer into the specified node. */ int _gnutls_x509_write_int (ASN1_TYPE node, const char *value, bigint_t mpi, int lz) { opaque *tmpstr; size_t s_len; int result; s_len = 0; if (lz) result = _gnutls_mpi_print_lz (mpi, NULL, &s_len); else result = _gnutls_mpi_print (mpi, NULL, &s_len); if (result != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert (); return result; } tmpstr = gnutls_malloc (s_len); if (tmpstr == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if (lz) result = _gnutls_mpi_print_lz (mpi, tmpstr, &s_len); else result = _gnutls_mpi_print (mpi, tmpstr, &s_len); if (result != 0) { gnutls_assert (); gnutls_free (tmpstr); return GNUTLS_E_MPI_PRINT_FAILED; } result = asn1_write_value (node, value, tmpstr, s_len); gnutls_free (tmpstr); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }
/* This calculates the SHA1(A | B) * A and B will be left-padded with zeros to fill n_size. */ bigint_t _gnutls_calc_srp_u(bigint_t A, bigint_t B, bigint_t n) { size_t b_size, a_size; uint8_t *holder, hd[MAX_HASH_SIZE]; size_t holder_size, hash_size, n_size; int ret; bigint_t res; /* get the size of n in bytes */ _gnutls_mpi_print(n, NULL, &n_size); _gnutls_mpi_print(A, NULL, &a_size); _gnutls_mpi_print(B, NULL, &b_size); 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(A, &holder[n_size - a_size], &a_size); _gnutls_mpi_print(B, &holder[n_size + n_size - b_size], &b_size); ret = _gnutls_hash_fast(GNUTLS_DIG_SHA1, holder, holder_size, hd); if (ret < 0) { gnutls_free(holder); gnutls_assert(); return NULL; } /* convert the bytes of hd to integer */ hash_size = 20; /* SHA */ ret = _gnutls_mpi_init_scan_nz(&res, hd, hash_size); gnutls_free(holder); if (ret < 0) { gnutls_assert(); return NULL; } return res; }
/* 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; }
static int _gnutls_srp_gx(uint8_t * text, size_t textsize, uint8_t ** result, bigint_t g, bigint_t prime) { bigint_t x, e = NULL; size_t result_size; int ret; if (_gnutls_mpi_init_scan_nz(&x, text, textsize)) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } ret = _gnutls_mpi_init(&e); if (ret < 0) goto cleanup; /* e = g^x mod prime (n) */ ret = _gnutls_mpi_powm(e, g, x, prime); if (ret < 0) goto cleanup; ret = _gnutls_mpi_print(e, NULL, &result_size); if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { *result = gnutls_malloc(result_size); if ((*result) == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } ret = _gnutls_mpi_print(e, *result, &result_size); if (ret < 0) goto cleanup; ret = result_size; } else { gnutls_assert(); ret = GNUTLS_E_MPI_PRINT_FAILED; } cleanup: _gnutls_mpi_release(&e); _gnutls_mpi_release(&x); return ret; }
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; }
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; }
void _gnutls_dump_mpi(const char *prefix, bigint_t a) { char buf[400]; char buf_hex[2 * sizeof(buf) + 1]; size_t n = sizeof buf; if (_gnutls_mpi_print(a, buf, &n)) strcpy(buf, "[can't print value]"); /* Flawfinder: ignore */ _gnutls_debug_log("MPI: length: %d\n\t%s%s\n", (int) n, prefix, _gnutls_bin2hex(buf, n, buf_hex, sizeof(buf_hex), NULL)); }
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; }
/* This function will copy the mpi data into a datum, * but will set minimum size to 'size'. That means that * the output value is left padded with zeros. */ int _gnutls_mpi_dprint_size (const bigint_t a, gnutls_datum_t * dest, size_t size) { int ret; opaque *buf = NULL; size_t bytes = 0; unsigned int i; if (dest == NULL || a == NULL) return GNUTLS_E_INVALID_REQUEST; _gnutls_mpi_print (a, NULL, &bytes); if (bytes != 0) buf = gnutls_malloc (MAX (size, bytes)); if (buf == NULL) return GNUTLS_E_MEMORY_ERROR; if (bytes <= size) { size_t diff = size - bytes; for (i = 0; i < diff; i++) buf[i] = 0; ret = _gnutls_mpi_print (a, &buf[diff], &bytes); } else { ret = _gnutls_mpi_print (a, buf, &bytes); } if (ret < 0) { gnutls_free (buf); return ret; } dest->data = buf; dest->size = MAX (size, bytes); return 0; }
/** * cdk_pk_get_keyid: * @pk: the public key * @keyid: buffer to store the key ID * * Calculate the key ID of the given public key. **/ u32 cdk_pk_get_keyid(cdk_pubkey_t pk, u32 * keyid) { u32 lowbits = 0; byte buf[24]; int rc; if (pk && (!pk->keyid[0] || !pk->keyid[1])) { if (pk->version < 4 && is_RSA(pk->pubkey_algo)) { byte p[MAX_MPI_BYTES]; size_t n; n = MAX_MPI_BYTES; rc = _gnutls_mpi_print(pk->mpi[0], p, &n); if (rc < 0 || n < 8) { keyid[0] = keyid[1] = (u32)-1; return (u32)-1; } pk->keyid[0] = p[n - 8] << 24 | p[n - 7] << 16 | p[n - 6] << 8 | p[n - 5]; pk->keyid[1] = p[n - 4] << 24 | p[n - 3] << 16 | p[n - 2] << 8 | p[n - 1]; } else if (pk->version == 4) { cdk_pk_get_fingerprint(pk, buf); pk->keyid[0] = _cdk_buftou32(buf + 12); pk->keyid[1] = _cdk_buftou32(buf + 16); } } lowbits = pk ? pk->keyid[1] : 0; if (keyid && pk) { keyid[0] = pk->keyid[0]; keyid[1] = pk->keyid[1]; } return lowbits; }
void _gnutls_mpi_log(const char *prefix, bigint_t a) { size_t binlen = 0; void *binbuf; size_t hexlen; char *hexbuf; int res; if (_gnutls_log_level < 2) return; res = _gnutls_mpi_print(a, NULL, &binlen); if (res < 0 && res != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert(); _gnutls_hard_log("MPI: %s can't print value (%d/%d)\n", prefix, res, (int) binlen); return; } if (binlen > 1024 * 1024) { gnutls_assert(); _gnutls_hard_log("MPI: %s too large mpi (%d)\n", prefix, (int) binlen); return; } binbuf = gnutls_malloc(binlen); if (!binbuf) { gnutls_assert(); _gnutls_hard_log("MPI: %s out of memory (%d)\n", prefix, (int) binlen); return; } res = _gnutls_mpi_print(a, binbuf, &binlen); if (res != 0) { gnutls_assert(); _gnutls_hard_log("MPI: %s can't print value (%d/%d)\n", prefix, res, (int) binlen); gnutls_free(binbuf); return; } hexlen = 2 * binlen + 1; hexbuf = gnutls_malloc(hexlen); if (!hexbuf) { gnutls_assert(); _gnutls_hard_log("MPI: %s out of memory (hex %d)\n", prefix, (int) hexlen); gnutls_free(binbuf); return; } _gnutls_bin2hex(binbuf, binlen, hexbuf, hexlen, NULL); _gnutls_hard_log("MPI: length: %d\n\t%s%s\n", (int) binlen, prefix, hexbuf); gnutls_free(hexbuf); gnutls_free(binbuf); }
/* ID should be: * 3 for MAC * 2 for IV * 1 for encryption key * * Note that this function produces different key for the * NULL password, and for the password with zero length. */ int _gnutls_pkcs12_string_to_key(const mac_entry_st * me, unsigned int id, const uint8_t * salt, unsigned int salt_size, unsigned int iter, const char *pw, unsigned int req_keylen, uint8_t * keybuf) { int rc; unsigned int i, j; digest_hd_st md; bigint_t num_b1 = NULL, num_ij = NULL; bigint_t mpi512 = NULL; unsigned int pwlen; uint8_t hash[MAX_HASH_SIZE], buf_b[64], buf_i[MAX_PASS_LEN * 2 + 64], *p; uint8_t d[64]; size_t cur_keylen; size_t n, m, p_size, i_size; unsigned mac_len; const uint8_t buf_512[] = /* 2^64 */ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; cur_keylen = 0; if (pw == NULL) pwlen = 0; else pwlen = strlen(pw); if (pwlen > MAX_PASS_LEN) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if ((rc = _pkcs12_check_pass(pw, pwlen)) < 0) { gnutls_assert(); return rc; } rc = _gnutls_mpi_init_scan(&mpi512, buf_512, sizeof(buf_512)); if (rc < 0) { gnutls_assert(); return rc; } /* Store salt and password in BUF_I */ p_size = ((pwlen / 64) * 64) + 64; if (p_size > sizeof(buf_i) - 64) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); p = buf_i; for (i = 0; i < 64; i++) *p++ = salt[i % salt_size]; if (pw) { for (i = j = 0; i < p_size; i += 2) { *p++ = 0; *p++ = pw[j]; if (++j > pwlen) /* Note, that we include the trailing (0) */ j = 0; } } else memset(p, 0, p_size); i_size = 64 + p_size; mac_len = _gnutls_mac_get_algo_len(me); for (;;) { rc = _gnutls_hash_init(&md, me); if (rc < 0) { gnutls_assert(); goto cleanup; } memset(d, id & 0xff, 64); _gnutls_hash(&md, d, 64); _gnutls_hash(&md, buf_i, pw ? i_size : 64); _gnutls_hash_deinit(&md, hash); for (i = 1; i < iter; i++) { rc = _gnutls_hash_fast(me->id, hash, mac_len, hash); if (rc < 0) { gnutls_assert(); goto cleanup; } } for (i = 0; i < mac_len && cur_keylen < req_keylen; i++) keybuf[cur_keylen++] = hash[i]; if (cur_keylen == req_keylen) { rc = 0; /* ready */ goto cleanup; } /* need more bytes. */ for (i = 0; i < 64; i++) buf_b[i] = hash[i % mac_len]; n = 64; rc = _gnutls_mpi_init_scan(&num_b1, buf_b, n); if (rc < 0) { gnutls_assert(); goto cleanup; } rc = _gnutls_mpi_add_ui(num_b1, num_b1, 1); if (rc < 0) { gnutls_assert(); goto cleanup; } for (i = 0; i < 128; i += 64) { n = 64; rc = _gnutls_mpi_init_scan(&num_ij, buf_i + i, n); if (rc < 0) { gnutls_assert(); goto cleanup; } rc = _gnutls_mpi_addm(num_ij, num_ij, num_b1, mpi512); if (rc < 0) { gnutls_assert(); goto cleanup; } n = 64; #ifndef PKCS12_BROKEN_KEYGEN m = (_gnutls_mpi_get_nbits(num_ij) + 7) / 8; #else m = n; #endif memset(buf_i + i, 0, n - m); rc = _gnutls_mpi_print(num_ij, buf_i + i + n - m, &n); if (rc < 0) { gnutls_assert(); goto cleanup; } _gnutls_mpi_release(&num_ij); } } cleanup: _gnutls_mpi_release(&num_ij); _gnutls_mpi_release(&num_b1); _gnutls_mpi_release(&mpi512); return rc; }
/* return A = g^a % N */ int _gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data) { size_t n_a; int ret; uint8_t *data_a; char *username, *password; char buf[64]; 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; } /* calc A = g^a % N */ if (G == NULL || N == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } A = _gnutls_calc_srp_A (&_a, G, N); if (A == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* Rest of 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 = (B - g^x) ^ (a + u * x) % N */ S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N); if (S == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_dump_mpi ("SRP B: ", B); _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; } if (_gnutls_mpi_print (NULL, &n_a, A) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } (*data) = gnutls_malloc (n_a + 2); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* copy A */ data_a = (*data); if (_gnutls_mpi_print (&data_a[2], &n_a, A) != 0) { gnutls_free (*data); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_hard_log ("INT: SRP A[%d]: %s\n", n_a, _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf))); _gnutls_mpi_release (&A); _gnutls_write_uint16 (n_a, data_a); return n_a + 2; }
/* 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; }
int _gnutls_gen_dh_common_client_kx (gnutls_session_t session, opaque ** data) { mpi_t x = NULL, X = NULL; size_t n_X; int ret; *data = NULL; X = gnutls_calc_dh_secret (&x, session->key->client_g, session->key->client_p); if (X == NULL || x == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x)); _gnutls_mpi_print (NULL, &n_X, X); (*data) = gnutls_malloc (n_X + 2); if (*data == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_mpi_print (&(*data)[2], &n_X, X); _gnutls_mpi_release (&X); _gnutls_write_uint16 (n_X, &(*data)[0]); /* calculate the key after calculating the message */ session->key->KEY = gnutls_calc_dh_key (session->key->client_Y, x, session->key->client_p); _gnutls_mpi_release (&x); if (session->key->KEY == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_dh_set_peer_public (session, session->key->client_Y); /* THESE SHOULD BE DISCARDED */ _gnutls_mpi_release (&session->key->client_Y); _gnutls_mpi_release (&session->key->client_p); _gnutls_mpi_release (&session->key->client_g); if (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters.current_cipher_suite) != GNUTLS_KX_DHE_PSK) { ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY); } else /* In DHE_PSK the key is set differently */ { gnutls_datum tmp_dh_key; ret = _gnutls_mpi_dprint (&tmp_dh_key, session->key->KEY); if (ret < 0) { gnutls_assert (); goto error; } ret = _gnutls_set_psk_session_key (session, &tmp_dh_key); _gnutls_free_datum (&tmp_dh_key); } _gnutls_mpi_release (&session->key->KEY); if (ret < 0) { gnutls_assert (); goto error; } return n_X + 2; error: _gnutls_mpi_release (&x); _gnutls_mpi_release (&X); gnutls_free (*data); *data = NULL; return ret; }
/* If the psk flag is set, then an empty psk_identity_hint will * be inserted */ int _gnutls_dh_common_print_server_kx (gnutls_session_t session, mpi_t g, mpi_t p, opaque ** data, int psk) { mpi_t x, X; size_t n_X, n_g, n_p; int ret, data_size, pos; uint8_t *pdata; X = gnutls_calc_dh_secret (&x, g, p); if (X == NULL || x == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } session->key->dh_secret = x; _gnutls_dh_set_secret_bits (session, _gnutls_mpi_get_nbits (x)); _gnutls_mpi_print (NULL, &n_g, g); _gnutls_mpi_print (NULL, &n_p, p); _gnutls_mpi_print (NULL, &n_X, X); data_size = n_g + n_p + n_X + 6; if (psk != 0) data_size += 2; (*data) = gnutls_malloc (data_size); if (*data == NULL) { _gnutls_mpi_release (&X); return GNUTLS_E_MEMORY_ERROR; } pos = 0; pdata = *data; if (psk != 0) { _gnutls_write_uint16 (0, &pdata[pos]); pos += 2; } _gnutls_mpi_print (&pdata[pos + 2], &n_p, p); _gnutls_write_uint16 (n_p, &pdata[pos]); pos += n_p + 2; _gnutls_mpi_print (&pdata[pos + 2], &n_g, g); _gnutls_write_uint16 (n_g, &pdata[pos]); pos += n_g + 2; _gnutls_mpi_print (&pdata[pos + 2], &n_X, X); _gnutls_mpi_release (&X); _gnutls_write_uint16 (n_X, &pdata[pos]); ret = data_size; return ret; }
/* 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; }
static int gen_rsa_export_server_kx (gnutls_session_t session, opaque ** data) { gnutls_rsa_params_t rsa_params; const bigint_t *rsa_mpis; size_t n_e, n_m; uint8_t *data_e, *data_m; int ret = 0, data_size; gnutls_cert *apr_cert_list; gnutls_privkey *apr_pkey; int apr_cert_list_length; gnutls_datum_t signature, ddata; cert_auth_info_t info; gnutls_certificate_credentials_t cred; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* find the appropriate certificate */ if ((ret = _gnutls_get_selected_cert (session, &apr_cert_list, &apr_cert_list_length, &apr_pkey)) < 0) { gnutls_assert (); return ret; } /* abort sending this message if we have a certificate * of 512 bits or less. */ if (apr_pkey && _gnutls_mpi_get_nbits (apr_pkey->params[0]) <= 512) { gnutls_assert (); return GNUTLS_E_INT_RET_0; } rsa_params = _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func, session); rsa_mpis = _gnutls_rsa_params_to_mpi (rsa_params); if (rsa_mpis == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, sizeof (cert_auth_info_st), 0)) < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]); _gnutls_mpi_print (rsa_mpis[0], NULL, &n_m); _gnutls_mpi_print (rsa_mpis[1], NULL, &n_e); (*data) = gnutls_malloc (n_e + n_m + 4); if (*data == NULL) { return GNUTLS_E_MEMORY_ERROR; } data_m = &(*data)[0]; _gnutls_mpi_print (rsa_mpis[0], &data_m[2], &n_m); _gnutls_write_uint16 (n_m, data_m); data_e = &data_m[2 + n_m]; _gnutls_mpi_print (rsa_mpis[1], &data_e[2], &n_e); _gnutls_write_uint16 (n_e, data_e); data_size = n_m + n_e + 4; /* Generate the signature. */ ddata.data = *data; ddata.size = data_size; if (apr_cert_list_length > 0) { if ((ret = _gnutls_tls_sign_params (session, &apr_cert_list[0], apr_pkey, &ddata, &signature)) < 0) { gnutls_assert (); gnutls_free (*data); *data = NULL; return ret; } } else { gnutls_assert (); return data_size; /* do not put a signature - ILLEGAL! */ } *data = gnutls_realloc_fast (*data, data_size + signature.size + 2); if (*data == NULL) { _gnutls_free_datum (&signature); gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_write_datum16 (&((*data)[data_size]), signature); data_size += signature.size + 2; _gnutls_free_datum (&signature); return data_size; }
/* 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; }
/* ID should be: * 3 for MAC * 2 for IV * 1 for encryption key */ int _gnutls_pkcs12_string_to_key (unsigned int id, const opaque * salt, unsigned int salt_size, unsigned int iter, const char *pw, unsigned int req_keylen, opaque * keybuf) { int rc; unsigned int i, j; digest_hd_st md; bigint_t num_b1 = NULL, num_ij = NULL; bigint_t mpi512 = NULL; unsigned int pwlen; opaque hash[20], buf_b[64], buf_i[128], *p; size_t cur_keylen; size_t n; const opaque buf_512[] = /* 2^64 */ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; cur_keylen = 0; if (pw == NULL) pwlen = 0; else pwlen = strlen (pw); if (pwlen > 63 / 2) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0) { gnutls_assert (); return rc; } rc = _gnutls_mpi_scan (&mpi512, buf_512, sizeof (buf_512)); if (rc < 0) { gnutls_assert (); return rc; } /* Store salt and password in BUF_I */ p = buf_i; for (i = 0; i < 64; i++) *p++ = salt[i % salt_size]; if (pw) { for (i = j = 0; i < 64; i += 2) { *p++ = 0; *p++ = pw[j]; if (++j > pwlen) /* Note, that we include the trailing zero */ j = 0; } } else memset (p, 0, 64); for (;;) { rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1); if (rc < 0) { gnutls_assert (); goto cleanup; } for (i = 0; i < 64; i++) { unsigned char lid = id & 0xFF; _gnutls_hash (&md, &lid, 1); } _gnutls_hash (&md, buf_i, pw ? 128 : 64); _gnutls_hash_deinit (&md, hash); for (i = 1; i < iter; i++) { rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_hash (&md, hash, 20); _gnutls_hash_deinit (&md, hash); } for (i = 0; i < 20 && cur_keylen < req_keylen; i++) keybuf[cur_keylen++] = hash[i]; if (cur_keylen == req_keylen) { rc = 0; /* ready */ goto cleanup; } /* need more bytes. */ for (i = 0; i < 64; i++) buf_b[i] = hash[i % 20]; n = 64; rc = _gnutls_mpi_scan (&num_b1, buf_b, n); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_mpi_add_ui (num_b1, num_b1, 1); for (i = 0; i < 128; i += 64) { n = 64; rc = _gnutls_mpi_scan (&num_ij, buf_i + i, n); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_mpi_addm (num_ij, num_ij, num_b1, mpi512); n = 64; rc = _gnutls_mpi_print (num_ij, buf_i + i, &n); if (rc < 0) { gnutls_assert (); goto cleanup; } _gnutls_mpi_release (&num_ij); } } cleanup: _gnutls_mpi_release (&num_ij); _gnutls_mpi_release (&num_b1); _gnutls_mpi_release (&mpi512); return rc; }