/* Always has the first bit zero */ int _gnutls_mpi_dprint_lz (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_lz (a, NULL, &bytes); if (bytes != 0) buf = gnutls_malloc (bytes); if (buf == NULL) return GNUTLS_E_MEMORY_ERROR; ret = _gnutls_mpi_print_lz (a, buf, &bytes); if (ret < 0) { gnutls_free (buf); return ret; } dest->data = buf; dest->size = bytes; return 0; }
/* 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; }
/* Encodes the RSA parameters into an ASN.1 RSA private key structure. */ static int _encode_rsa (ASN1_TYPE * c2, mpi_t * params) { int result, i; size_t size[8], total; opaque *m_data, *pube_data, *prie_data; opaque *p1_data, *p2_data, *u_data, *exp1_data, *exp2_data; opaque *all_data = NULL, *p; mpi_t exp1 = NULL, exp2 = NULL, q1 = NULL, p1 = NULL, u = NULL; opaque null = '\0'; /* Read all the sizes */ total = 0; for (i = 0; i < 5; i++) { _gnutls_mpi_print_lz (NULL, &size[i], params[i]); total += size[i]; } /* Now generate exp1 and exp2 */ exp1 = _gnutls_mpi_salloc_like (params[0]); /* like modulus */ if (exp1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } exp2 = _gnutls_mpi_salloc_like (params[0]); if (exp2 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } q1 = _gnutls_mpi_salloc_like (params[4]); if (q1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p1 = _gnutls_mpi_salloc_like (params[3]); if (p1 == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } u = _gnutls_mpi_salloc_like (params[3]); if (u == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } _gnutls_mpi_invm (u, params[4], params[3]); /* inverse of q mod p */ _gnutls_mpi_print_lz (NULL, &size[5], u); total += size[5]; _gnutls_mpi_sub_ui (p1, params[3], 1); _gnutls_mpi_sub_ui (q1, params[4], 1); _gnutls_mpi_mod (exp1, params[2], p1); _gnutls_mpi_mod (exp2, params[2], q1); /* calculate exp's size */ _gnutls_mpi_print_lz (NULL, &size[6], exp1); total += size[6]; _gnutls_mpi_print_lz (NULL, &size[7], exp2); total += size[7]; /* Encoding phase. * allocate data enough to hold everything */ all_data = gnutls_secure_malloc (total); if (all_data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p = all_data; m_data = p; p += size[0]; pube_data = p; p += size[1]; prie_data = p; p += size[2]; p1_data = p; p += size[3]; p2_data = p; p += size[4]; u_data = p; p += size[5]; exp1_data = p; p += size[6]; exp2_data = p; _gnutls_mpi_print_lz (m_data, &size[0], params[0]); _gnutls_mpi_print_lz (pube_data, &size[1], params[1]); _gnutls_mpi_print_lz (prie_data, &size[2], params[2]); _gnutls_mpi_print_lz (p1_data, &size[3], params[3]); _gnutls_mpi_print_lz (p2_data, &size[4], params[4]); _gnutls_mpi_print_lz (u_data, &size[5], u); _gnutls_mpi_print_lz (exp1_data, &size[6], exp1); _gnutls_mpi_print_lz (exp2_data, &size[7], exp2); /* Ok. Now we have the data. Create the asn1 structures */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Write PRIME */ if ((result = asn1_write_value (*c2, "modulus", m_data, size[0])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "publicExponent", pube_data, size[1])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "privateExponent", prie_data, size[2])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "prime1", p1_data, size[3])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "prime2", p2_data, size[4])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "exponent1", exp1_data, size[6])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "exponent2", exp2_data, size[7])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "coefficient", u_data, size[5])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } _gnutls_mpi_release (&exp1); _gnutls_mpi_release (&exp2); _gnutls_mpi_release (&q1); _gnutls_mpi_release (&p1); _gnutls_mpi_release (&u); gnutls_free (all_data); if ((result = asn1_write_value (*c2, "otherPrimeInfos", NULL, 0)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } return 0; cleanup: _gnutls_mpi_release (&u); _gnutls_mpi_release (&exp1); _gnutls_mpi_release (&exp2); _gnutls_mpi_release (&q1); _gnutls_mpi_release (&p1); asn1_delete_structure (c2); gnutls_free (all_data); return result; }
/* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure. */ static int _encode_dsa (ASN1_TYPE * c2, mpi_t * params) { int result, i; size_t size[DSA_PRIVATE_PARAMS], total; opaque *p_data, *q_data, *g_data, *x_data, *y_data; opaque *all_data = NULL, *p; opaque null = '\0'; /* Read all the sizes */ total = 0; for (i = 0; i < DSA_PRIVATE_PARAMS; i++) { _gnutls_mpi_print_lz (NULL, &size[i], params[i]); total += size[i]; } /* Encoding phase. * allocate data enough to hold everything */ all_data = gnutls_secure_malloc (total); if (all_data == NULL) { gnutls_assert (); result = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p = all_data; p_data = p; p += size[0]; q_data = p; p += size[1]; g_data = p; p += size[2]; y_data = p; p += size[3]; x_data = p; _gnutls_mpi_print_lz (p_data, &size[0], params[0]); _gnutls_mpi_print_lz (q_data, &size[1], params[1]); _gnutls_mpi_print_lz (g_data, &size[2], params[2]); _gnutls_mpi_print_lz (y_data, &size[3], params[3]); _gnutls_mpi_print_lz (x_data, &size[4], params[4]); /* Ok. Now we have the data. Create the asn1 structures */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPrivateKey", c2)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* Write PRIME */ if ((result = asn1_write_value (*c2, "p", p_data, size[0])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "q", q_data, size[1])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "g", g_data, size[2])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "Y", y_data, size[3])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } if ((result = asn1_write_value (*c2, "priv", x_data, size[4])) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } gnutls_free (all_data); if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } return 0; cleanup: asn1_delete_structure (c2); gnutls_free (all_data); return result; }
/** * gnutls_dh_params_export_pkcs3 - export DH params to a pkcs3 structure * @params: Holds the DH parameters * @format: the format of output params. One of PEM or DER. * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters) * * This function will export the given dh parameters to a PKCS3 * DHParams structure. This is the format generated by "openssl dhparam" tool. * If the buffer provided is not long enough to hold the output, then * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned. * * If the structure is PEM encoded, it will have a header * of "BEGIN DH PARAMETERS". * * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned, * otherwise an error code is returned. **/ int gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params, gnutls_x509_crt_fmt_t format, unsigned char *params_data, size_t * params_data_size) { ASN1_TYPE c2; int result, _params_data_size; size_t g_size, p_size; opaque *p_data, *g_data; opaque *all_data; _gnutls_mpi_print_lz (params->params[1], NULL, &g_size); _gnutls_mpi_print_lz (params->params[0], NULL, &p_size); all_data = gnutls_malloc (g_size + p_size); if (all_data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } p_data = &all_data[0]; g_data = &all_data[p_size]; _gnutls_mpi_print_lz (params->params[0], p_data, &p_size); _gnutls_mpi_print_lz (params->params[1], g_data, &g_size); /* Ok. Now we have the data. Create the asn1 structures */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2)) != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (all_data); return _gnutls_asn2err (result); } /* Write PRIME */ if ((result = asn1_write_value (c2, "prime", p_data, p_size)) != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (all_data); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } /* Write the GENERATOR */ if ((result = asn1_write_value (c2, "base", g_data, g_size)) != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (all_data); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } gnutls_free (all_data); if ((result = asn1_write_value (c2, "privateValueLength", NULL, 0)) != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } if (format == GNUTLS_X509_FMT_DER) { if (params_data == NULL) *params_data_size = 0; _params_data_size = *params_data_size; result = asn1_der_coding (c2, "", params_data, &_params_data_size, NULL); *params_data_size = _params_data_size; asn1_delete_structure (&c2); if (result != ASN1_SUCCESS) { gnutls_assert (); if (result == ASN1_MEM_ERROR) return GNUTLS_E_SHORT_MEMORY_BUFFER; return _gnutls_asn2err (result); } } else { /* PEM */ opaque *tmp; opaque *out; int len; len = 0; asn1_der_coding (c2, "", NULL, &len, NULL); tmp = gnutls_malloc (len); if (tmp == NULL) { gnutls_assert (); asn1_delete_structure (&c2); return GNUTLS_E_MEMORY_ERROR; } if ((result = asn1_der_coding (c2, "", tmp, &len, NULL)) != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (tmp); asn1_delete_structure (&c2); return _gnutls_asn2err (result); } asn1_delete_structure (&c2); result = _gnutls_fbase64_encode ("DH PARAMETERS", tmp, len, &out); gnutls_free (tmp); if (result < 0) { gnutls_assert (); return result; } if (result == 0) { /* oooops */ gnutls_assert (); gnutls_free (out); return GNUTLS_E_INTERNAL_ERROR; } if ((unsigned) result > *params_data_size) { gnutls_assert (); gnutls_free (out); *params_data_size = result; return GNUTLS_E_SHORT_MEMORY_BUFFER; } *params_data_size = result - 1; if (params_data) memcpy (params_data, out, result); gnutls_free (out); } return 0; }
/** * gnutls_dh_params_export2_pkcs3: * @params: Holds the DH parameters * @format: the format of output params. One of PEM or DER. * @out: will contain a PKCS3 DHParams structure PEM or DER encoded * * This function will export the given dh parameters to a PKCS3 * DHParams structure. This is the format generated by "openssl dhparam" tool. * The data in @out will be allocated using gnutls_malloc(). * * If the structure is PEM encoded, it will have a header * of "BEGIN DH PARAMETERS". * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since: 3.1.3 **/ int gnutls_dh_params_export2_pkcs3(gnutls_dh_params_t params, gnutls_x509_crt_fmt_t format, gnutls_datum_t * out) { ASN1_TYPE c2; int result; size_t g_size, p_size; uint8_t *p_data, *g_data; uint8_t *all_data; _gnutls_mpi_print_lz(params->params[1], NULL, &g_size); _gnutls_mpi_print_lz(params->params[0], NULL, &p_size); all_data = gnutls_malloc(g_size + p_size); if (all_data == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } p_data = &all_data[0]; _gnutls_mpi_print_lz(params->params[0], p_data, &p_size); g_data = &all_data[p_size]; _gnutls_mpi_print_lz(params->params[1], g_data, &g_size); /* Ok. Now we have the data. Create the asn1 structures */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2)) != ASN1_SUCCESS) { gnutls_assert(); gnutls_free(all_data); return _gnutls_asn2err(result); } /* Write PRIME */ if ((result = asn1_write_value(c2, "prime", p_data, p_size)) != ASN1_SUCCESS) { gnutls_assert(); gnutls_free(all_data); asn1_delete_structure(&c2); return _gnutls_asn2err(result); } if (params->q_bits > 0) result = _gnutls_x509_write_uint32(c2, "privateValueLength", params->q_bits); else result = asn1_write_value(c2, "privateValueLength", NULL, 0); if (result < 0) { gnutls_assert(); gnutls_free(all_data); asn1_delete_structure(&c2); return _gnutls_asn2err(result); } /* Write the GENERATOR */ if ((result = asn1_write_value(c2, "base", g_data, g_size)) != ASN1_SUCCESS) { gnutls_assert(); gnutls_free(all_data); asn1_delete_structure(&c2); return _gnutls_asn2err(result); } gnutls_free(all_data); if (format == GNUTLS_X509_FMT_DER) { result = _gnutls_x509_der_encode(c2, "", out, 0); asn1_delete_structure(&c2); if (result < 0) return gnutls_assert_val(result); } else { /* PEM */ gnutls_datum_t t; result = _gnutls_x509_der_encode(c2, "", &t, 0); asn1_delete_structure(&c2); if (result < 0) return gnutls_assert_val(result); result = _gnutls_fbase64_encode("DH PARAMETERS", t.data, t.size, out); gnutls_free(t.data); if (result < 0) { gnutls_assert(); return result; } } return 0; }