diff options
Diffstat (limited to 'lib/gnutls_pk.c')
-rw-r--r-- | lib/gnutls_pk.c | 1289 |
1 files changed, 658 insertions, 631 deletions
diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c index fa49381d96..fce507b6de 100644 --- a/lib/gnutls_pk.c +++ b/lib/gnutls_pk.c @@ -36,162 +36,173 @@ #include <x509/mpi.h> #include <x509/common.h> -static int _gnutls_pk_encrypt(int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey, int pkey_len); -static int _gnutls_pk_sign(int algo, mpi_t* data, mpi_t hash, mpi_t * pkey, int); -static int _gnutls_pk_verify(int algo, mpi_t hash, mpi_t* data, mpi_t *pkey, int); -static int _gnutls_pk_decrypt(int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey, int); +static int _gnutls_pk_encrypt(int algo, mpi_t * resarr, mpi_t data, + mpi_t * pkey, int pkey_len); +static int _gnutls_pk_sign(int algo, mpi_t * data, mpi_t hash, + mpi_t * pkey, int); +static int _gnutls_pk_verify(int algo, mpi_t hash, mpi_t * data, + mpi_t * pkey, int); +static int _gnutls_pk_decrypt(int algo, mpi_t * resarr, mpi_t data, + mpi_t * pkey, int); /* Do PKCS-1 RSA encryption. * params is modulus, public exp. */ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, - const gnutls_datum *plaintext, mpi_t* params, - uint params_len, - uint btype) + const gnutls_datum * plaintext, + mpi_t * params, uint params_len, uint 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 ( (ret=_gnutls_get_random(ps, psize, GNUTLS_STRONG_RANDOM)) < 0) { - gnutls_assert(); - gnutls_afree(edata); - return ret; - } - for (i = 0; i < psize; i++) { - opaque rnd[3]; - - /* Read three random bytes that will be - * used to replace the zeros. - */ - if ( (ret=_gnutls_get_random( rnd, 3, GNUTLS_STRONG_RANDOM)) < 0) { - gnutls_assert(); - gnutls_afree(edata); - return ret; - } - /* use non zero values for - * the first two. - */ - if (rnd[0]==0) rnd[0] = 0xaf; - if (rnd[1]==0) rnd[1] = 0xae; - - if (ps[i] == 0) { - /* If the first one is zero then set it to rnd[0]. - * If the second one is zero then set it to rnd[1]. - * Otherwise add (mod 256) the two previous ones plus rnd[3], or use - * rnd[1] if the value == 0. - */ - if (i<2) ps[i] = rnd[i]; - else ps[i] = GMAX( rnd[3] + ps[i-1] + ps[i-2], rnd[1]); - } - } - 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(&m, edata, &k) != 0) { + 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 ((ret = + _gnutls_get_random(ps, psize, GNUTLS_STRONG_RANDOM)) < 0) { + gnutls_assert(); + gnutls_afree(edata); + return ret; + } + for (i = 0; i < psize; i++) { + opaque rnd[3]; + + /* Read three random bytes that will be + * used to replace the zeros. + */ + if ((ret = + _gnutls_get_random(rnd, 3, GNUTLS_STRONG_RANDOM)) < 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; - } + } + /* use non zero values for + * the first two. + */ + if (rnd[0] == 0) + rnd[0] = 0xaf; + if (rnd[1] == 0) + rnd[1] = 0xae; + + if (ps[i] == 0) { + /* If the first one is zero then set it to rnd[0]. + * If the second one is zero then set it to rnd[1]. + * Otherwise add (mod 256) the two previous ones plus rnd[3], or use + * rnd[1] if the value == 0. + */ + if (i < 2) + ps[i] = rnd[i]; + else + ps[i] = GMAX(rnd[3] + ps[i - 1] + ps[i - 2], rnd[1]); + } + } + 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; + } - _gnutls_mpi_print(NULL, &psize, res); + ps[psize] = 0; + memcpy(&ps[psize + 1], plaintext->data, plaintext->size); - 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; - } + if (_gnutls_mpi_scan(&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->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; + ciphertext->size = k; - _gnutls_mpi_release(&res); + _gnutls_mpi_release(&res); - return 0; + return 0; } @@ -200,309 +211,322 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, * Can decrypt block type 1 and type 2 packets. */ int _gnutls_pkcs1_rsa_decrypt(gnutls_datum * plaintext, - const gnutls_datum *ciphertext, mpi_t* params, uint params_len, - uint btype) + const gnutls_datum * ciphertext, + mpi_t * params, uint params_len, uint btype) { - uint 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(&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); - + uint 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(&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); - /* EB = 00||BT||PS||00||D - * (use block type 'btype') - */ + _gnutls_mpi_release(&res); + /* EB = 00||BT||PS||00||D + * (use block type 'btype') + */ - edata[0] = 0; - esize++; - if (edata[0] != 0 || edata[1] != btype) { - gnutls_assert(); - gnutls_afree(edata); - return GNUTLS_E_DECRYPTION_FAILED; - } + edata[0] = 0; + esize++; - 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"); - ret = GNUTLS_E_PKCS1_WRONG_PAD; - break; - } - } + 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; - default: - gnutls_assert(); - gnutls_afree(edata); - return GNUTLS_E_INTERNAL_ERROR; + } } - i++; - - if (ret < 0) { - gnutls_assert(); - gnutls_afree(edata); - return GNUTLS_E_DECRYPTION_FAILED; + 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"); + ret = GNUTLS_E_PKCS1_WRONG_PAD; + break; + } } + break; + default: + gnutls_assert(); + gnutls_afree(edata); + return GNUTLS_E_INTERNAL_ERROR; + } + i++; - if (_gnutls_sset_datum(plaintext, &edata[i], esize - i) < 0) { - gnutls_assert(); - gnutls_afree(edata); - return GNUTLS_E_MEMORY_ERROR; - } + 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; + return 0; } -int _gnutls_rsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertext, - mpi_t *params, int params_len, int btype) { +int _gnutls_rsa_verify(const gnutls_datum * vdata, + const gnutls_datum * ciphertext, mpi_t * params, + int params_len, int btype) +{ - gnutls_datum plain; - int ret; + gnutls_datum plain; + int ret; - /* decrypt signature */ - if ( (ret=_gnutls_pkcs1_rsa_decrypt( &plain, ciphertext, params, params_len, btype)) < 0) { - gnutls_assert(); - return ret; - } + /* decrypt signature */ + if ((ret = + _gnutls_pkcs1_rsa_decrypt(&plain, ciphertext, params, params_len, + btype)) < 0) { + gnutls_assert(); + return ret; + } - if (plain.size != vdata->size) { - gnutls_assert(); - _gnutls_free_datum( &plain); - return GNUTLS_E_PK_SIG_VERIFY_FAILED; - } + if (plain.size != vdata->size) { + gnutls_assert(); + _gnutls_free_datum(&plain); + return GNUTLS_E_PK_SIG_VERIFY_FAILED; + } - if ( memcmp(plain.data, vdata->data, plain.size)!=0) { - gnutls_assert(); - _gnutls_free_datum( &plain); - return GNUTLS_E_PK_SIG_VERIFY_FAILED; - } + if (memcmp(plain.data, vdata->data, plain.size) != 0) { + gnutls_assert(); + _gnutls_free_datum(&plain); + return GNUTLS_E_PK_SIG_VERIFY_FAILED; + } - _gnutls_free_datum( &plain); + _gnutls_free_datum(&plain); - return 0; /* ok */ + return 0; /* ok */ } /* encodes the Dss-Sig-Value structure */ -static int encode_ber_rs( gnutls_datum* sig_value, mpi_t r, mpi_t s) { -ASN1_TYPE sig; -int result, tot_len; - - if ((result=asn1_create_element( _gnutls_get_gnutls_asn(), "GNUTLS.DSASignatureValue", - &sig))!=ASN1_SUCCESS) { - gnutls_assert(); - return _gnutls_asn2err(result); - } +static int encode_ber_rs(gnutls_datum * sig_value, mpi_t r, mpi_t s) +{ + ASN1_TYPE sig; + int result, tot_len; + + if ((result = + asn1_create_element(_gnutls_get_gnutls_asn(), + "GNUTLS.DSASignatureValue", + &sig)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = _gnutls_x509_write_int(sig, "r", r, 1); + if (result < 0) { + gnutls_assert(); + asn1_delete_structure(&sig); + return result; + } - result = _gnutls_x509_write_int( sig, "r", r, 1); - if ( result < 0) { - gnutls_assert(); - asn1_delete_structure(&sig); - return result; - } + result = _gnutls_x509_write_int(sig, "s", s, 1); + if (result < 0) { + gnutls_assert(); + asn1_delete_structure(&sig); + return result; + } - result = _gnutls_x509_write_int( sig, "s", s, 1); - if (result < 0) { - gnutls_assert(); - asn1_delete_structure(&sig); - return result; - } + tot_len = 0; - tot_len = 0; - - result = _gnutls_x509_der_encode( sig, "", sig_value, 0); + result = _gnutls_x509_der_encode(sig, "", sig_value, 0); - asn1_delete_structure(&sig); + asn1_delete_structure(&sig); - if (result < 0) { - gnutls_assert(); - return result; - } + if (result < 0) { + gnutls_assert(); + return result; + } - return 0; + return 0; } /* Do DSA signature calculation. params is p, q, g, y, x in that order. */ -int _gnutls_dsa_sign(gnutls_datum * signature, const gnutls_datum *hash, +int _gnutls_dsa_sign(gnutls_datum * signature, const gnutls_datum * hash, mpi_t * params, uint 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(&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; + 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(&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; } /* decodes the Dss-Sig-Value structure */ -static int decode_ber_rs( const gnutls_datum* sig_value, mpi_t* r, mpi_t* s) { -ASN1_TYPE sig; -int result; +static int decode_ber_rs(const gnutls_datum * sig_value, mpi_t * r, + mpi_t * s) +{ + ASN1_TYPE sig; + int result; + + if ((result = + asn1_create_element(_gnutls_get_gnutls_asn(), + "GNUTLS.DSASignatureValue", + &sig)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = + asn1_der_decoding(&sig, sig_value->data, sig_value->size, NULL); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + asn1_delete_structure(&sig); + return _gnutls_asn2err(result); + } - if ((result=asn1_create_element( _gnutls_get_gnutls_asn(), "GNUTLS.DSASignatureValue", &sig))!=ASN1_SUCCESS) { - gnutls_assert(); - return _gnutls_asn2err(result); - } + result = _gnutls_x509_read_int(sig, "r", r); + if (result < 0) { + gnutls_assert(); + asn1_delete_structure(&sig); + return result; + } - result = asn1_der_decoding( &sig, sig_value->data, sig_value->size, NULL); - if (result != ASN1_SUCCESS) { - gnutls_assert(); - asn1_delete_structure(&sig); - return _gnutls_asn2err(result); - } - - result = - _gnutls_x509_read_int( sig, "r", r); - if (result < 0) { - gnutls_assert(); - asn1_delete_structure(&sig); - return result; - } + result = _gnutls_x509_read_int(sig, "s", s); + if (result < 0) { + gnutls_assert(); + _gnutls_mpi_release(s); + asn1_delete_structure(&sig); + return result; + } - result = - _gnutls_x509_read_int( sig, "s", s); - if (result < 0) { - gnutls_assert(); - _gnutls_mpi_release( s); - asn1_delete_structure(&sig); - return result; - } + asn1_delete_structure(&sig); - asn1_delete_structure(&sig); - - return 0; + return 0; } /* params is p, q, g, y in that order */ -int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *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(&mdata, vdata->data, &k) != 0) { - gnutls_assert(); - return GNUTLS_E_MPI_SCAN_FAILED; - } - - /* decrypt signature */ - ret=_gnutls_pk_verify( GCRY_PK_DSA, mdata, rs, params, - params_len); - _gnutls_mpi_release(&mdata); - - if (ret < 0) { - gnutls_assert(); - return ret; - } +int _gnutls_dsa_verify(const gnutls_datum * vdata, + const gnutls_datum * sig_value, mpi_t * params, + int params_len) +{ - return 0; /* ok */ + 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(&mdata, vdata->data, &k) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + /* decrypt signature */ + ret = _gnutls_pk_verify(GCRY_PK_DSA, mdata, rs, params, params_len); + _gnutls_mpi_release(&mdata); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; /* ok */ } @@ -513,295 +537,298 @@ int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *sig_value * Emulate our old PK interface here - sometime in the future we might * change the internal design to directly fit to libgcrypt. */ -static int _gnutls_pk_encrypt(int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey, int pkey_len) +static int _gnutls_pk_encrypt(int algo, mpi_t * resarr, mpi_t data, + mpi_t * pkey, int pkey_len) { - gcry_sexp_t s_ciph, s_data, s_pkey; - int rc=-1; - - /* make a sexp from pkey */ - switch (algo) { - case GCRY_PK_RSA: - if (pkey_len >= 2) - rc = gcry_sexp_build(&s_pkey, NULL, - "(public-key(rsa(n%m)(e%m)))", - pkey[0], pkey[1]); - break; + gcry_sexp_t s_ciph, s_data, s_pkey; + int rc = -1; + + /* make a sexp from pkey */ + switch (algo) { + case GCRY_PK_RSA: + if (pkey_len >= 2) + rc = gcry_sexp_build(&s_pkey, NULL, + "(public-key(rsa(n%m)(e%m)))", + pkey[0], pkey[1]); + break; + + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + /* 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_INTERNAL_ERROR; + } - default: - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } + /* pass it to libgcrypt */ + rc = gcry_pk_encrypt(&s_ciph, s_data, s_pkey); + gcry_sexp_release(s_data); + gcry_sexp_release(s_pkey); - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_PK_ENCRYPTION_FAILED; - /* 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_INTERNAL_ERROR; + } else { /* add better error handling or make gnupg use S-Exp directly */ + gcry_sexp_t list = gcry_sexp_find_token(s_ciph, "a", 0); + if (list == NULL) { + gnutls_assert(); + gcry_sexp_release(s_ciph); + return GNUTLS_E_INTERNAL_ERROR; } - /* pass it to libgcrypt */ - rc = gcry_pk_encrypt(&s_ciph, s_data, s_pkey); - gcry_sexp_release(s_data); - gcry_sexp_release(s_pkey); + resarr[0] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_PK_ENCRYPTION_FAILED; - - } else { /* add better error handling or make gnupg use S-Exp directly */ - gcry_sexp_t list = gcry_sexp_find_token(s_ciph, "a", 0); - if (list == NULL) { - gnutls_assert(); - gcry_sexp_release(s_ciph); - return GNUTLS_E_INTERNAL_ERROR; - } - - resarr[0] = gcry_sexp_nth_mpi(list, 1, 0); - gcry_sexp_release(list); - - if (resarr[0] == NULL) { - gnutls_assert(); - gcry_sexp_release(s_ciph); - return GNUTLS_E_INTERNAL_ERROR; - } + if (resarr[0] == NULL) { + gnutls_assert(); + gcry_sexp_release(s_ciph); + return GNUTLS_E_INTERNAL_ERROR; } + } - gcry_sexp_release(s_ciph); - return rc; + gcry_sexp_release(s_ciph); + return rc; } -static -int _gnutls_pk_decrypt(int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey, int pkey_len) +static +int _gnutls_pk_decrypt(int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey, + int pkey_len) { - gcry_sexp_t s_plain, s_data, s_pkey; - int rc=-1; - - /* make a sexp from pkey */ - switch (algo) { - case GCRY_PK_RSA: - if (pkey_len >=6) - rc = gcry_sexp_build(&s_pkey, NULL, - "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", - pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]); - - break; - - default: - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } - - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } - - /* put the data into a simple list */ - if (gcry_sexp_build(&s_data, NULL, "(enc-val(rsa(a%m)))", data)) { - gnutls_assert(); - gcry_sexp_release(s_pkey); - return GNUTLS_E_INTERNAL_ERROR; - } - - /* pass it to libgcrypt */ - rc = gcry_pk_decrypt(&s_plain, s_data, s_pkey); - gcry_sexp_release(s_data); + gcry_sexp_t s_plain, s_data, s_pkey; + int rc = -1; + + /* make a sexp from pkey */ + switch (algo) { + case GCRY_PK_RSA: + if (pkey_len >= 6) + rc = gcry_sexp_build(&s_pkey, NULL, + "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", + pkey[0], pkey[1], pkey[2], pkey[3], + pkey[4], pkey[5]); + + break; + + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + /* put the data into a simple list */ + if (gcry_sexp_build(&s_data, NULL, "(enc-val(rsa(a%m)))", data)) { + gnutls_assert(); gcry_sexp_release(s_pkey); + return GNUTLS_E_INTERNAL_ERROR; + } - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_PK_DECRYPTION_FAILED; + /* pass it to libgcrypt */ + rc = gcry_pk_decrypt(&s_plain, s_data, s_pkey); + gcry_sexp_release(s_data); + gcry_sexp_release(s_pkey); - } else { /* add better error handling or make gnupg use S-Exp directly */ - resarr[0] = gcry_sexp_nth_mpi(s_plain, 0, 0); + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_PK_DECRYPTION_FAILED; - if (resarr[0] == NULL) { - gnutls_assert(); - gcry_sexp_release(s_plain); - return GNUTLS_E_INTERNAL_ERROR; - } + } else { /* add better error handling or make gnupg use S-Exp directly */ + resarr[0] = gcry_sexp_nth_mpi(s_plain, 0, 0); + + if (resarr[0] == NULL) { + gnutls_assert(); + gcry_sexp_release(s_plain); + return GNUTLS_E_INTERNAL_ERROR; } + } - gcry_sexp_release(s_plain); - return rc; + gcry_sexp_release(s_plain); + return rc; } /* in case of DSA puts into data, r,s */ -static -int _gnutls_pk_sign(int algo, mpi_t* data, mpi_t hash, mpi_t * pkey, int pkey_len) +static +int _gnutls_pk_sign(int algo, mpi_t * data, mpi_t hash, mpi_t * pkey, + int pkey_len) { - gcry_sexp_t s_hash, s_key, s_sig; - int rc=-1; - - /* make a sexp from pkey */ - switch (algo) { - case GCRY_PK_DSA: - if (pkey_len >= 5) - rc = gcry_sexp_build(&s_key, NULL, - "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", - pkey[0], pkey[1], pkey[2], - pkey[3], pkey[4]); - else { - gnutls_assert(); - } - - break; - case GCRY_PK_RSA: - if (pkey_len >=6) - rc = gcry_sexp_build(&s_key, NULL, - "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", - pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]); - else { - gnutls_assert(); - } - break; - - default: - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; + gcry_sexp_t s_hash, s_key, s_sig; + int rc = -1; + + /* make a sexp from pkey */ + switch (algo) { + case GCRY_PK_DSA: + if (pkey_len >= 5) + rc = gcry_sexp_build(&s_key, NULL, + "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", + pkey[0], pkey[1], pkey[2], + pkey[3], pkey[4]); + else { + gnutls_assert(); } - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; + break; + case GCRY_PK_RSA: + if (pkey_len >= 6) + rc = gcry_sexp_build(&s_key, NULL, + "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", + pkey[0], pkey[1], pkey[2], pkey[3], + pkey[4], pkey[5]); + else { + gnutls_assert(); } + break; - /* put the data into a simple list */ - if (gcry_sexp_build(&s_hash, NULL, "%m", hash)) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } - /* pass it to libgcrypt */ - rc = gcry_pk_sign(&s_sig, s_hash, s_key); - gcry_sexp_release(s_hash); - gcry_sexp_release(s_key); + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_PK_SIGN_FAILED; - - } else { - gcry_sexp_t list; - - if (algo==GCRY_PK_DSA) { - list = gcry_sexp_find_token( s_sig, "r" , 0); - if (list == NULL) { - gnutls_assert(); - gcry_sexp_release(s_sig); - return GNUTLS_E_INTERNAL_ERROR; - } - - data[0] = gcry_sexp_nth_mpi( list, 1, 0 ); - gcry_sexp_release (list); - - list = gcry_sexp_find_token( s_sig, "s" , 0); - if (list == NULL) { - gnutls_assert(); - gcry_sexp_release(s_sig); - return GNUTLS_E_INTERNAL_ERROR; - } - - data[1] = gcry_sexp_nth_mpi( list, 1, 0 ); - gcry_sexp_release (list); - } else { /* GCRY_PK_RSA */ - list = gcry_sexp_find_token( s_sig, "s" , 0); - if (list == NULL) { - gnutls_assert(); - gcry_sexp_release(s_sig); - return GNUTLS_E_INTERNAL_ERROR; - } - - data[0] = gcry_sexp_nth_mpi( list, 1, 0 ); - gcry_sexp_release (list); - } - } + /* put the data into a simple list */ + if (gcry_sexp_build(&s_hash, NULL, "%m", hash)) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } - gcry_sexp_release(s_sig); - return 0; -} + /* pass it to libgcrypt */ + rc = gcry_pk_sign(&s_sig, s_hash, s_key); + gcry_sexp_release(s_hash); + gcry_sexp_release(s_key); + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_PK_SIGN_FAILED; -static int _gnutls_pk_verify(int algo, mpi_t hash, mpi_t* data, mpi_t *pkey, int pkey_len) -{ - gcry_sexp_t s_sig, s_hash, s_pkey; - int rc=-1; - - /* make a sexp from pkey */ - switch (algo) { - case GCRY_PK_DSA: - if (pkey_len >= 4) - 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]); - break; - case GCRY_PK_RSA: - if (pkey_len >= 2) - rc = gcry_sexp_build(&s_pkey, NULL, - "(public-key(rsa(n%m)(e%m)))", - pkey[0], pkey[1]); - break; + } else { + gcry_sexp_t list; - default: + if (algo == GCRY_PK_DSA) { + list = gcry_sexp_find_token(s_sig, "r", 0); + if (list == NULL) { gnutls_assert(); + gcry_sexp_release(s_sig); return GNUTLS_E_INTERNAL_ERROR; - } + } - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; - } + data[0] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); - /* put the data into a simple list */ - if (gcry_sexp_build(&s_hash, NULL, "%m", hash)) { + list = gcry_sexp_find_token(s_sig, "s", 0); + if (list == NULL) { gnutls_assert(); - gcry_sexp_release(s_pkey); + gcry_sexp_release(s_sig); return GNUTLS_E_INTERNAL_ERROR; - } + } - switch (algo) { - case GCRY_PK_DSA: - rc = gcry_sexp_build(&s_sig, NULL, - "(sig-val(dsa(r%m)(s%m)))", - data[0], data[1]); - break; - case GCRY_PK_RSA: - rc = gcry_sexp_build(&s_sig, NULL, - "(sig-val(rsa(s%m)))", - data[0]); - break; - - default: + data[1] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); + } else { /* GCRY_PK_RSA */ + list = gcry_sexp_find_token(s_sig, "s", 0); + if (list == NULL) { gnutls_assert(); - gcry_sexp_release(s_pkey); - gcry_sexp_release(s_hash); + gcry_sexp_release(s_sig); return GNUTLS_E_INTERNAL_ERROR; - } + } - if (rc != 0) { - gnutls_assert(); - gcry_sexp_release(s_pkey); - gcry_sexp_release(s_hash); - return GNUTLS_E_INTERNAL_ERROR; + data[0] = gcry_sexp_nth_mpi(list, 1, 0); + gcry_sexp_release(list); } + } - rc = gcry_pk_verify( s_sig, s_hash, s_pkey); - - gcry_sexp_release(s_sig); + gcry_sexp_release(s_sig); + return 0; +} + + +static int _gnutls_pk_verify(int algo, mpi_t hash, mpi_t * data, + mpi_t * pkey, int pkey_len) +{ + gcry_sexp_t s_sig, s_hash, s_pkey; + int rc = -1; + + /* make a sexp from pkey */ + switch (algo) { + case GCRY_PK_DSA: + if (pkey_len >= 4) + 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]); + break; + case GCRY_PK_RSA: + if (pkey_len >= 2) + rc = gcry_sexp_build(&s_pkey, NULL, + "(public-key(rsa(n%m)(e%m)))", + pkey[0], pkey[1]); + break; + + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + /* put the data into a simple list */ + if (gcry_sexp_build(&s_hash, NULL, "%m", hash)) { + gnutls_assert(); + gcry_sexp_release(s_pkey); + return GNUTLS_E_INTERNAL_ERROR; + } + + switch (algo) { + case GCRY_PK_DSA: + rc = gcry_sexp_build(&s_sig, NULL, + "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]); + break; + case GCRY_PK_RSA: + rc = gcry_sexp_build(&s_sig, NULL, "(sig-val(rsa(s%m)))", data[0]); + break; + + default: + gnutls_assert(); + gcry_sexp_release(s_pkey); gcry_sexp_release(s_hash); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (rc != 0) { + gnutls_assert(); gcry_sexp_release(s_pkey); + gcry_sexp_release(s_hash); + return GNUTLS_E_INTERNAL_ERROR; + } - if (rc != 0) { - gnutls_assert(); - return GNUTLS_E_PK_SIG_VERIFY_FAILED; - } + rc = gcry_pk_verify(s_sig, s_hash, s_pkey); + + gcry_sexp_release(s_sig); + gcry_sexp_release(s_hash); + gcry_sexp_release(s_pkey); + + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_PK_SIG_VERIFY_FAILED; + } - return 0; + return 0; } |