diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-01-26 23:01:52 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-01-26 23:01:52 +0000 |
commit | 36d88b8cb6dea5f3aa11ba5c3f4ccc64d64b36ba (patch) | |
tree | b2f6b840c3c1195b631b01ce9f93ede4112bd197 /lib/gnutls_pk.c | |
parent | c9c1d23b48fdd5cec55753937ddfc1307fb4be13 (diff) | |
download | gnutls-36d88b8cb6dea5f3aa11ba5c3f4ccc64d64b36ba.tar.gz |
Added stuff for DSS certificates (not ready yet)
Diffstat (limited to 'lib/gnutls_pk.c')
-rw-r--r-- | lib/gnutls_pk.c | 329 |
1 files changed, 294 insertions, 35 deletions
diff --git a/lib/gnutls_pk.c b/lib/gnutls_pk.c index a906547917..a7a27cb80f 100644 --- a/lib/gnutls_pk.c +++ b/lib/gnutls_pk.c @@ -29,13 +29,17 @@ #include <gnutls_datum.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); + /* Do PKCS-1 RSA encryption. * pkey is the public key and n the modulus. */ -int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext, - MPI pkey, MPI n, int btype) +int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, + gnutls_datum plaintext, MPI pkey, MPI n, + int btype) { int k, psize, i, ret; MPI m, res; @@ -64,30 +68,30 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext, psize = k - 3 - plaintext.size; ps = &edata[2]; - switch(btype) { - case 2: + switch (btype) { + case 2: _gnutls_get_random(ps, psize, GNUTLS_WEAK_RANDOM); for (i = 0; i < psize; i++) { if (ps[i] == 0) ps[i] = 0xff; } break; - case 1: + case 1: for (i = 0; i < psize; i++) ps[i] = 0xff; - break; + break; #ifdef ALLOW_BLOCK_0 - case 0: + case 0: for (i = 0; i < psize; i++) { ps[i] = 0x00; } - break; + break; #endif - default: - gnutls_assert(); - return GNUTLS_E_UNKNOWN_ERROR; + default: + gnutls_assert(); + return GNUTLS_E_UNKNOWN_ERROR; } - + ps[psize] = 0; memcpy(&ps[psize + 1], plaintext.data, plaintext.size); @@ -108,7 +112,7 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext, return ret; } - _gnutls_mpi_print( NULL, &psize, res); + _gnutls_mpi_print(NULL, &psize, res); ciphertext->data = gnutls_malloc(psize); if (ciphertext->data == NULL) { @@ -116,7 +120,7 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext, _gnutls_mpi_release(&res); return GNUTLS_E_MEMORY_ERROR; } - _gnutls_mpi_print( ciphertext->data, &psize, res); + _gnutls_mpi_print(ciphertext->data, &psize, res); ciphertext->size = psize; _gnutls_mpi_release(&res); @@ -129,8 +133,9 @@ int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext, * pkey is the private key and n the modulus. * Can decrypt block type 1 and type packets. */ -int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, gnutls_datum ciphertext, - MPI pkey, MPI n, int btype) +int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, + gnutls_datum ciphertext, MPI pkey, MPI n, + int btype) { int k, esize, i, ret; MPI c, res; @@ -162,14 +167,14 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, gnutls_datum ciphertext return ret; } - _gnutls_mpi_print( NULL, &esize, res); - edata = gnutls_malloc(esize+1); + _gnutls_mpi_print(NULL, &esize, res); + edata = gnutls_malloc(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_print(&edata[1], &esize, res); _gnutls_mpi_release(&res); @@ -188,8 +193,8 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, gnutls_datum ciphertext } ret = GNUTLS_E_DECRYPTION_FAILED; - switch(btype) { - case 2: + switch (btype) { + case 2: for (i = 2; i < esize; i++) { if (edata[i] == 0) { ret = 0; @@ -197,7 +202,7 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, gnutls_datum ciphertext } } break; - case 1: + case 1: for (i = 2; i < esize; i++) { if (edata[i] == 0 && i > 2) { ret = 0; @@ -208,30 +213,144 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, gnutls_datum ciphertext break; } } - break; - default: - gnutls_assert(); - return GNUTLS_E_UNKNOWN_ERROR; + break; + default: + gnutls_assert(); + return GNUTLS_E_UNKNOWN_ERROR; } i++; - + if (ret < 0) { gnutls_assert(); gnutls_free(edata); return GNUTLS_E_DECRYPTION_FAILED; } - - if (gnutls_sset_datum( plaintext, &edata[i], esize - i) < 0) { + + if (gnutls_sset_datum(plaintext, &edata[i], esize - i) < 0) { gnutls_assert(); gnutls_free(edata); return GNUTLS_E_MEMORY_ERROR; } - + gnutls_free(edata); return 0; } + +int _gnutls_rsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertext, + MPI pkey, MPI n, int btype) { + + gnutls_datum plain; + int ret; + + /* decrypt signature */ + if ( (ret=_gnutls_pkcs1_rsa_decrypt( &plain, *ciphertext, pkey, n, btype)) < 0) { + gnutls_assert(); + return ret; + } + + if (plain.size != vdata->size) { + gnutls_assert(); + gnutls_sfree_datum( &plain); + return GNUTLS_E_PK_SIGNATURE_FAILED; + } + + if ( memcmp(plain.data, vdata->data, plain.size)!=0) { + gnutls_assert(); + gnutls_sfree_datum( &plain); + return GNUTLS_E_PK_SIGNATURE_FAILED; + } + + gnutls_sfree_datum( &plain); + + return 0; /* ok */ +} + + +/* Do DSA signature calculation + */ +int _gnutls_dsa_sign(gnutls_datum * signature, gnutls_datum plaintext, + MPI p, MPI q, MPI g, MPI y) +{ + MPI res[2], mdata; + int sig_size; + MPI *_pkey[DSA_PARAMS]; + int k, ret, psize; + + k = plaintext.size; + if (_gnutls_mpi_scan(&mdata, plaintext.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); + /* res now holds r,s */ + _gnutls_mpi_release(&mdata); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + +#error FIX r,s + + _gnutls_mpi_print(NULL, &sig_size, res[0]); + + signature->data = gnutls_malloc(sig_size); + if (signature->data == NULL) { + gnutls_assert(); + _gnutls_mpi_release(&res[0]); + return GNUTLS_E_MEMORY_ERROR; + } + _gnutls_mpi_print(signature->data, &psize, res[0]); + signature->size = psize; + + _gnutls_mpi_release(&res[0]); + + return 0; +} + +int _gnutls_dsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertext, + MPI p, MPI q, MPI g, MPI y) { + + MPI mdata; + int ret, k; + MPI *_pkey[DSA_PARAMS]; + MPI *_data[2]; + MPI r, s; + + #error FIX r,s + + k = vdata->size; + if (_gnutls_mpi_scan(&mdata, vdata->data, &k) != 0) { + gnutls_assert(); + return GNUTLS_E_MPI_SCAN_FAILED; + } + + /* 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) { + _gnutls_mpi_release(&mdata); + gnutls_assert(); + return ret; + } + _gnutls_mpi_release(&mdata); + + return 0; /* ok */ +} + + /* this is taken from gnupg */ @@ -239,17 +358,20 @@ int _gnutls_pkcs1_rsa_decrypt(gnutls_sdatum * plaintext, gnutls_datum ciphertext * 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; /* make a sexp from pkey */ - if (algo == GCRY_PK_RSA) { + switch (algo) { + case GCRY_PK_RSA: rc = gcry_sexp_build(&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", *pkey[0], *pkey[1]); - } else { + break; + + default: gnutls_assert(); return GNUTLS_E_UNKNOWN_KX_ALGORITHM; } @@ -272,8 +394,8 @@ int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI **pkey) if (rc != 0) { gnutls_assert(); - return GNUTLS_E_UNKNOWN_ERROR; - + return GNUTLS_E_PK_ENCRYPTION_FAILED; + } else { /* add better error handling or make gnupg use S-Exp directly */ GCRY_SEXP list = gcry_sexp_find_token(s_ciph, "a", 0); if (list == NULL) { @@ -295,3 +417,140 @@ int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI **pkey) gcry_sexp_release(s_ciph); return rc; } + +/* in case of DSA puts into data, r,s + */ +static +int _gnutls_pk_sign(int algo, MPI* data, MPI hash, MPI ** pkey) +{ + GCRY_SEXP s_hash, s_key, s_sig; + int rc; + + /* make a sexp from 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]); + break; + + default: + gnutls_assert(); + return GNUTLS_E_UNKNOWN_KX_ALGORITHM; + } + + if (rc != 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL; + } + + /* put the data into a simple list */ + if (gcry_sexp_build(&s_hash, NULL, "%m", hash)) { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_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_PK_ENCRYPTION_FAILED; + + } else { + GCRY_SEXP list = gcry_sexp_find_token( s_sig, "r" , 0); + if (list == NULL) { + gnutls_assert(); + gcry_sexp_release(s_sig); + return GNUTLS_E_INTERNAL; + } + + 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; + } + + data[1] = gcry_sexp_nth_mpi( list, 1, 0 ); + gcry_sexp_release (list); + + } + + gcry_sexp_release(s_sig); + return 0; +} + + +static int _gnutls_pk_verify(int algo, MPI hash, MPI** data, MPI **pkey) +{ + GCRY_SEXP s_sig, s_hash, s_pkey; + int rc; + + /* make a sexp from pkey */ + switch (algo) { + 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]); + break; + + default: + gnutls_assert(); + return GNUTLS_E_UNKNOWN_KX_ALGORITHM; + } + + if (rc != 0) { + gnutls_assert(); + gcry_sexp_release(s_pkey); + return GNUTLS_E_INTERNAL; + } + + /* 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_UNKNOWN_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; + + default: + gnutls_assert(); + gcry_sexp_release(s_pkey); + gcry_sexp_release(s_sig); + return GNUTLS_E_UNKNOWN_KX_ALGORITHM; + } + + if (rc != 0) { + gnutls_assert(); + gcry_sexp_release(s_pkey); + gcry_sexp_release(s_sig); + return GNUTLS_E_INTERNAL; + } + + 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_SIGNATURE_FAILED; + } + + return 0; +} |