summaryrefslogtreecommitdiff
path: root/lib/gnutls_pk.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gnutls_pk.c')
-rw-r--r--lib/gnutls_pk.c256
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;
}