diff options
Diffstat (limited to 'lib/gnutls_pk.c')
-rw-r--r-- | lib/gnutls_pk.c | 256 |
1 files changed, 180 insertions, 76 deletions
diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c index a7a27cb80f..cd999e9f9c 100644 --- a/lib/gnutls_pk.c +++ b/lib/gnutls_pk.c @@ -27,26 +27,27 @@ #include <gnutls_errors.h> #include <gnutls_random.h> #include <gnutls_datum.h> +#include <gnutls_global.h> +#include <x509_der.h> #include "debug.h" -static int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI ** pkey); -static int _gnutls_pk_verify(int algo, MPI hash, MPI** data, MPI **pkey); +static int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI * pkey); +static int _gnutls_pk_verify(int algo, MPI hash, MPI* data, MPI *pkey); /* Do PKCS-1 RSA encryption. - * pkey is the public key and n the modulus. + * params is modulus, public exp. */ - int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, - gnutls_datum plaintext, MPI pkey, MPI n, + gnutls_datum plaintext, MPI* params, int btype) { int k, psize, i, ret; MPI m, res; opaque *edata, *ps; - MPI *_pkey[2]; + MPI tmp_params[RSA_PARAMS]; - k = gcry_mpi_get_nbits(n) / 8; + k = gcry_mpi_get_nbits(params[0]) / 8; if (plaintext.size > k - 11) { gnutls_assert(); @@ -70,6 +71,10 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, ps = &edata[2]; switch (btype) { case 2: + /* using public key */ + tmp_params[0] = params[0]; + tmp_params[1] = params[1]; + _gnutls_get_random(ps, psize, GNUTLS_WEAK_RANDOM); for (i = 0; i < psize; i++) { if (ps[i] == 0) @@ -77,6 +82,10 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, } break; case 1: + /* using private key */ + tmp_params[0] = params[0]; + tmp_params[1] = params[2]; + for (i = 0; i < psize; i++) ps[i] = 0xff; break; @@ -102,9 +111,7 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, } gnutls_free(edata); - _pkey[0] = &n; - _pkey[1] = &pkey; - ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, m, _pkey); + ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, m, tmp_params); _gnutls_mpi_release(&m); if (ret < 0) { @@ -130,19 +137,18 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, /* Do PKCS-1 RSA decryption. - * pkey is the private key and n the modulus. + * params is modulus, public exp. * Can decrypt block type 1 and type packets. */ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, - gnutls_datum ciphertext, MPI pkey, MPI n, + gnutls_datum ciphertext, MPI* params, int btype) { int k, esize, i, ret; MPI c, res; opaque *edata; - MPI *_pkey[2]; - k = gcry_mpi_get_nbits(n) / 8; + k = gcry_mpi_get_nbits(params[0]) / 8; esize = ciphertext.size; if (esize != k) { @@ -155,11 +161,7 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, return GNUTLS_E_MPI_SCAN_FAILED; } - - _pkey[0] = &n; - _pkey[1] = &pkey; - - ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, c, _pkey); + ret = _gnutls_pk_encrypt(GCRY_PK_RSA, &res, c, params); _gnutls_mpi_release(&c); if (ret < 0) { @@ -239,13 +241,13 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, int _gnutls_rsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertext, - MPI pkey, MPI n, int btype) { + MPI *params, int btype) { gnutls_datum plain; int ret; /* decrypt signature */ - if ( (ret=_gnutls_pkcs1_rsa_decrypt( &plain, *ciphertext, pkey, n, btype)) < 0) { + if ( (ret=_gnutls_pkcs1_rsa_decrypt( &plain, *ciphertext, params, btype)) < 0) { gnutls_assert(); return ret; } @@ -267,28 +269,92 @@ int _gnutls_rsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertex return 0; /* ok */ } +/* encodes the Dss-Sig-Value structure + */ +static int encode_ber_rs( gnutls_datum* sig_value, MPI r, MPI s) { +node_asn* sig; +int result; +opaque str[MAX_PARAMETER_SIZE]; +int len = sizeof(str); +int tot_len = 0; + + if (asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.DSASignatureValue", + &sig, "sig")!=ASN_OK) { + gnutls_assert(); + return GNUTLS_E_ASN1_ERROR; + } + + if ( _gnutls_mpi_print( str, &len, r) < 0) { + gnutls_assert(); + asn1_delete_structure(sig); + return GNUTLS_E_MPI_PRINT_FAILED; + } + tot_len += len; + + result = asn1_write_value( sig, "sig.r", str, len); + + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(sig); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + len = sizeof(str) - 1; + if ( _gnutls_mpi_print( str, &len, s) < 0) { + gnutls_assert(); + asn1_delete_structure(sig); + return GNUTLS_E_MPI_PRINT_FAILED; + } + tot_len += len; + + result = asn1_write_value( sig, "sig.s", str, len); + + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(sig); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + sig_value->size = tot_len + 100; + sig_value->data = gnutls_malloc( sig_value->size); + if (sig_value->data==NULL) { + gnutls_assert(); + asn1_delete_structure(sig); + } + + result = asn1_create_der( sig, "sig", sig_value->data, &sig_value->size); + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(sig); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + asn1_delete_structure(sig); + + return 0; +} + -/* Do DSA signature calculation +/* Do DSA signature calculation. params is p, q, g, y, x in that order. */ -int _gnutls_dsa_sign(gnutls_datum * signature, gnutls_datum plaintext, - MPI p, MPI q, MPI g, MPI y) +int _gnutls_dsa_sign(gnutls_datum * signature, const gnutls_datum *hash, + MPI * params) { - MPI res[2], mdata; - int sig_size; - MPI *_pkey[DSA_PARAMS]; - int k, ret, psize; + MPI rs[2], mdata; + int k, ret; + + k = hash->size; + if (k!=20) { /* SHA only */ + gnutls_assert(); + return GNUTLS_E_PK_SIGNATURE_FAILED; + } - k = plaintext.size; - if (_gnutls_mpi_scan(&mdata, plaintext.data, &k) != 0) { + if (_gnutls_mpi_scan(&mdata, hash->data, &k) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } - _pkey[0] = &p; - _pkey[1] = &q; - _pkey[2] = &g; - _pkey[3] = &y; - ret = _gnutls_pk_sign(GCRY_PK_DSA, res, mdata, _pkey); + ret = _gnutls_pk_sign(GCRY_PK_DSA, rs, mdata, params); /* res now holds r,s */ _gnutls_mpi_release(&mdata); @@ -297,34 +363,80 @@ int _gnutls_dsa_sign(gnutls_datum * signature, gnutls_datum plaintext, return ret; } -#error FIX r,s + if (encode_ber_rs( signature, rs[0], rs[1])!=0) { + gnutls_assert(); + _gnutls_mpi_release(&rs[0]); + _gnutls_mpi_release(&rs[1]); + return GNUTLS_E_MEMORY_ERROR; + } + + /* free r,s */ + _gnutls_mpi_release(&rs[0]); + _gnutls_mpi_release(&rs[1]); + + return 0; +} + +/* decodes the Dss-Sig-Value structure + */ +static int decode_ber_rs( const gnutls_datum* sig_value, MPI* r, MPI* s) { +node_asn* sig; +int result; +opaque str[MAX_PARAMETER_SIZE]; - _gnutls_mpi_print(NULL, &sig_size, res[0]); - signature->data = gnutls_malloc(sig_size); - if (signature->data == NULL) { + if (asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.DSASignatureValue", &sig, "sig")!=ASN_OK) { gnutls_assert(); - _gnutls_mpi_release(&res[0]); - return GNUTLS_E_MEMORY_ERROR; + return GNUTLS_E_ASN1_ERROR; + } + + result = asn1_get_der( sig, sig_value->data, sig_value->size); + if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(sig); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + result = + _gnutls_x509_read_int( sig, "sig.r", str, sizeof(str)-1, r); + if (result < 0) { + gnutls_assert(); + asn1_delete_structure(sig); + return result; } - _gnutls_mpi_print(signature->data, &psize, res[0]); - signature->size = psize; - _gnutls_mpi_release(&res[0]); + result = + _gnutls_x509_read_int( sig, "sig.s", str, sizeof(str)-1, s); + if (result < 0) { + gnutls_assert(); + _gnutls_mpi_release( s); + asn1_delete_structure(sig); + return result; + } + asn1_delete_structure(sig); + return 0; } -int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertext, - MPI p, MPI q, MPI g, MPI y) { +/* params is p, q, g, y in that order + */ +int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *sig_value, + MPI * params) { MPI mdata; int ret, k; - MPI *_pkey[DSA_PARAMS]; - MPI *_data[2]; - MPI r, s; - - #error FIX r,s + MPI rs[2]; + + if (vdata->size != 20) { /* sha-1 only */ + gnutls_assert(); + return GNUTLS_E_INTERNAL; + } + + 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(&mdata, vdata->data, &k) != 0) { @@ -333,14 +445,7 @@ int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertex } /* decrypt signature */ - _pkey[0] = &p; - _pkey[1] = &q; - _pkey[2] = &g; - _pkey[3] = &y; - - _data[0] = &r; - _data[1] = &s; - if ( (ret=_gnutls_pk_verify( GCRY_PK_DSA, mdata, _data, _pkey)) < 0) { + if ( (ret=_gnutls_pk_verify( GCRY_PK_DSA, mdata, rs, params)) < 0) { _gnutls_mpi_release(&mdata); gnutls_assert(); return ret; @@ -358,7 +463,7 @@ int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertex * Emulate our old PK interface here - sometime in the future we might * change the internal design to directly fit to libgcrypt. */ -int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI ** pkey) +int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI * pkey) { GCRY_SEXP s_ciph, s_data, s_pkey; int rc; @@ -368,7 +473,7 @@ int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI ** pkey) case GCRY_PK_RSA: rc = gcry_sexp_build(&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", - *pkey[0], *pkey[1]); + pkey[0], pkey[1]); break; default: @@ -384,6 +489,7 @@ int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI ** pkey) /* put the data into a simple list */ if (gcry_sexp_build(&s_data, NULL, "%m", data)) { gnutls_assert(); + gcry_sexp_release(s_pkey); return GNUTLS_E_UNKNOWN_ERROR; } @@ -410,7 +516,7 @@ int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI ** pkey) if (resarr[0] == NULL) { gnutls_assert(); gcry_sexp_release(s_ciph); - return GNUTLS_E_UNKNOWN_ERROR; + return GNUTLS_E_INTERNAL; } } @@ -421,7 +527,7 @@ int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI ** pkey) /* in case of DSA puts into data, r,s */ static -int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI ** pkey) +int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI * pkey) { GCRY_SEXP s_hash, s_key, s_sig; int rc; @@ -430,9 +536,9 @@ int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI ** pkey) switch (algo) { case GCRY_PK_DSA: rc = gcry_sexp_build(&s_key, NULL, - "(public-key(rsa(p%m)(q%m)(g%m)(y%m)(x%m)))", - *pkey[0], *pkey[1], *pkey[2], - *pkey[3], *pkey[4]); + "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", + pkey[0], pkey[1], pkey[2], + pkey[3], pkey[4]); break; default: @@ -458,7 +564,7 @@ int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI ** pkey) if (rc != 0) { gnutls_assert(); - return GNUTLS_E_PK_ENCRYPTION_FAILED; + return GNUTLS_E_PK_SIGNATURE_FAILED; } else { GCRY_SEXP list = gcry_sexp_find_token( s_sig, "r" , 0); @@ -488,7 +594,7 @@ int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI ** pkey) } -static int _gnutls_pk_verify(int algo, MPI hash, MPI** data, MPI **pkey) +static int _gnutls_pk_verify(int algo, MPI hash, MPI* data, MPI *pkey) { GCRY_SEXP s_sig, s_hash, s_pkey; int rc; @@ -498,18 +604,16 @@ static int _gnutls_pk_verify(int algo, MPI hash, MPI** data, MPI **pkey) case GCRY_PK_DSA: rc = gcry_sexp_build(&s_pkey, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", - pkey[0], pkey[1], pkey[2], - pkey[3]); + pkey[0], pkey[1], pkey[2], pkey[3]); break; default: gnutls_assert(); - return GNUTLS_E_UNKNOWN_KX_ALGORITHM; + return GNUTLS_E_INTERNAL; } if (rc != 0) { gnutls_assert(); - gcry_sexp_release(s_pkey); return GNUTLS_E_INTERNAL; } @@ -524,20 +628,20 @@ static int _gnutls_pk_verify(int algo, MPI hash, MPI** data, MPI **pkey) case GCRY_PK_DSA: rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(dsa(r%m)(s%m)))", - *data[0], *data[1]); + data[0], data[1]); break; default: gnutls_assert(); gcry_sexp_release(s_pkey); - gcry_sexp_release(s_sig); - return GNUTLS_E_UNKNOWN_KX_ALGORITHM; + gcry_sexp_release(s_hash); + return GNUTLS_E_INTERNAL; } if (rc != 0) { gnutls_assert(); gcry_sexp_release(s_pkey); - gcry_sexp_release(s_sig); + gcry_sexp_release(s_hash); return GNUTLS_E_INTERNAL; } |