summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2002-01-26 23:01:52 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2002-01-26 23:01:52 +0000
commit36d88b8cb6dea5f3aa11ba5c3f4ccc64d64b36ba (patch)
treeb2f6b840c3c1195b631b01ce9f93ede4112bd197
parentc9c1d23b48fdd5cec55753937ddfc1307fb4be13 (diff)
downloadgnutls-36d88b8cb6dea5f3aa11ba5c3f4ccc64d64b36ba.tar.gz
Added stuff for DSS certificates (not ready yet)
-rw-r--r--lib/Makefile.am8
-rw-r--r--lib/auth_x509.c29
-rw-r--r--lib/ext_max_record.c2
-rw-r--r--lib/gnutls.asn (renamed from lib/pkcs1.asn)24
-rw-r--r--lib/gnutls_buffers.c28
-rw-r--r--lib/gnutls_cert.c367
-rw-r--r--lib/gnutls_cert.h28
-rw-r--r--lib/gnutls_errors.c1
-rw-r--r--lib/gnutls_errors_int.h5
-rw-r--r--lib/gnutls_extensions.c1
-rw-r--r--lib/gnutls_global.c12
-rw-r--r--lib/gnutls_global.h2
-rw-r--r--lib/gnutls_handshake.c6
-rw-r--r--lib/gnutls_int.h4
-rw-r--r--lib/gnutls_pk.c329
-rw-r--r--lib/gnutls_pk.h4
-rw-r--r--lib/gnutls_privkey.c155
-rw-r--r--lib/gnutls_privkey.h3
-rw-r--r--lib/gnutls_sig.c86
-rw-r--r--lib/pkix.asn5
-rw-r--r--lib/x509_sig_check.c13
21 files changed, 903 insertions, 209 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ff816415de..552d16acc3 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,7 +4,7 @@ bin_SCRIPTS = libgnutls-config
m4datadir = $(datadir)/aclocal
m4data_DATA = libgnutls.m4
-EXTRA_DIST = debug.h gnutls_compress.h defines.h pkcs1.asn pkix.asn \
+EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls.asn pkix.asn \
gnutls_cipher.h gnutls_buffers.h gnutls_errors.h gnutls_int.h \
gnutls_handshake.h gnutls_num.h gnutls_algorithms.h gnutls_dh.h \
gnutls_kx.h gnutls_hash_int.h gnutls_cipher_int.h gnutls_db.h \
@@ -34,7 +34,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \
gnutls_datum.c auth_rsa.c gnutls_session_pack.c \
gnutls_gcry.c gnutls_pk.c gnutls_cert.c x509_verify.c\
gnutls_global.c gnutls_privkey.c gnutls_constate.c gnutls_anon_cred.c \
- x509_sig_check.c pkix_asn1_tab.c pkcs1_asn1_tab.c gnutls_mem.c \
+ x509_sig_check.c pkix_asn1_tab.c gnutls_asn1_tab.c gnutls_mem.c \
x509_extensions.c auth_x509.c gnutls_ui.c gnutls_sig.c auth_dhe_rsa.c \
gnutls_dh_primes.c ext_max_record.c gnutls_alert.c gnutls_int_compat.c \
gnutls_str.c
@@ -49,8 +49,8 @@ libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
pkix_asn1_tab.c: pkix.asn
-../src/asn1c pkix.asn pkix_asn1_tab.c
-pkcs1_asn1_tab.c: pkcs1.asn
- -../src/asn1c pkcs1.asn pkcs1_asn1_tab.c
+gnutls_asn1_tab.c: gnutls.asn
+ -../src/asn1c gnutls.asn gnutls_asn1_tab.c
gnutls-api.tex: $(COBJECTS)
@echo "\\newpage" > gnutls-api.tex
diff --git a/lib/auth_x509.c b/lib/auth_x509.c
index 0e2ae0a39c..fafed43535 100644
--- a/lib/auth_x509.c
+++ b/lib/auth_x509.c
@@ -607,16 +607,15 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data,
return 0;
}
-
-#ifdef DEBUG
-# warning CHECK FOR DSS
-#endif
-
-#define RSA_SIGN 1
+enum CertificateSigType { RSA_SIGN=1, DSA_SIGN=2 };
+/* Checks if we support the given signature algorithm
+ * (RSA or DSA). Returns 0 if true.
+ */
int _gnutls_check_supported_sign_algo(uint8 algo)
{
switch (algo) {
case RSA_SIGN:
+ case DSA_SIGN:
return 0;
}
@@ -653,7 +652,7 @@ int _gnutls_proc_x509_cert_req(GNUTLS_STATE state, opaque * data,
size = p[0];
p += 1;
- /* FIXME: Add support for DSS certificates too
+ /* check if the sign algorithm is supported.
*/
found = 0;
for (i = 0; i < size; i++, p++) {
@@ -674,6 +673,9 @@ int _gnutls_proc_x509_cert_req(GNUTLS_STATE state, opaque * data,
return 0;
}
+ /* now we ask the user to tell which one
+ * he wants to use.
+ */
DECR_LEN(dsize, size);
if ((ret =
_gnutls_find_acceptable_client_cert(state, p, size,
@@ -782,7 +784,7 @@ int _gnutls_proc_x509_client_cert_vrfy(GNUTLS_STATE state, opaque * data,
return 0;
}
-#define CERTTYPE_SIZE 2
+#define CERTTYPE_SIZE 3
int _gnutls_gen_x509_server_cert_req(GNUTLS_STATE state, opaque ** data)
{
const GNUTLS_X509PKI_CREDENTIALS cred;
@@ -814,10 +816,9 @@ int _gnutls_gen_x509_server_cert_req(GNUTLS_STATE state, opaque ** data)
}
pdata[0] = CERTTYPE_SIZE - 1;
-#ifdef DEBUG
-# warning CHECK HERE FOR DSS
-#endif
- pdata[1] = RSA_SIGN; /* only this for now */
+
+ pdata[1] = RSA_SIGN;
+ pdata[2] = DSA_SIGN; /* only these for now */
pdata += CERTTYPE_SIZE;
WRITEdatum16(pdata, cred->rdn_sequence);
@@ -848,6 +849,7 @@ int _gnutls_find_apr_cert(GNUTLS_STATE state, gnutls_cert ** apr_cert_list,
return GNUTLS_E_INSUFICIENT_CRED;
}
+
if (state->security_parameters.entity == GNUTLS_SERVER) {
if (cred->ncerts == 0) {
@@ -882,6 +884,9 @@ int _gnutls_find_apr_cert(GNUTLS_STATE state, gnutls_cert ** apr_cert_list,
/* it is allowed not to have a certificate
*/
} else {
+ /* we had already decided which certificate
+ * to send.
+ */
ind =
state->gnutls_internals.
client_certificate_index;
diff --git a/lib/ext_max_record.c b/lib/ext_max_record.c
index b33adf809e..1ffef22004 100644
--- a/lib/ext_max_record.c
+++ b/lib/ext_max_record.c
@@ -38,8 +38,6 @@ int _gnutls_max_record_recv_params( GNUTLS_STATE state, const opaque* data, int
if (state->security_parameters.entity == GNUTLS_SERVER) {
if (data_size > 0) {
- gnutls_assert();
-
if ( data_size != 1) {
gnutls_assert();
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
diff --git a/lib/pkcs1.asn b/lib/gnutls.asn
index d04dacabbc..da195bfec6 100644
--- a/lib/pkcs1.asn
+++ b/lib/gnutls.asn
@@ -1,11 +1,11 @@
-PKCS-1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) modules(0) pkcs-1(1)}
+GNUTLS { 0 }
DEFINITIONS EXPLICIT TAGS ::=
BEGIN
-
--- Main structures
+-- This file contains parts of PKCS-1 structures and some stuff
+-- required for DSA keys.
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
@@ -60,5 +60,21 @@ DigestAlgorithmIdentifier ::= AlgorithmIdentifier
Digest ::= OCTET STRING
+DSAPublicKey ::= INTEGER
+
+DSAParameters ::= SEQUENCE {
+ p INTEGER,
+ q INTEGER,
+ g INTEGER
+}
+
+DSAPrivateKey ::= SEQUENCE {
+ version INTEGER, -- should be zero
+ p INTEGER,
+ q INTEGER,
+ g INTEGER,
+ Y INTEGER, -- public
+ priv INTEGER
+}
-END \ No newline at end of file
+END
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index c821a1ba02..aec196d0a2 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -160,7 +160,7 @@ int _gnutls_record_buffer_get(ContentType type, GNUTLS_STATE state, char *data,
memcpy(data, state->gnutls_internals.application_data_buffer.data, length);
/* overwrite buffer */
- memcpy(state->gnutls_internals.application_data_buffer.data,
+ memmove(state->gnutls_internals.application_data_buffer.data,
&state->gnutls_internals.application_data_buffer.data[length],
state->gnutls_internals.application_data_buffer.size);
state->gnutls_internals.application_data_buffer.data =
@@ -179,7 +179,7 @@ int _gnutls_record_buffer_get(ContentType type, GNUTLS_STATE state, char *data,
memcpy(data, state->gnutls_internals.handshake_data_buffer.data, length);
/* overwrite buffer */
- memcpy(state->gnutls_internals.handshake_data_buffer.data,
+ memmove(state->gnutls_internals.handshake_data_buffer.data,
&state->gnutls_internals.handshake_data_buffer.data[length],
state->gnutls_internals.handshake_data_buffer.size);
state->gnutls_internals.handshake_data_buffer.data =
@@ -902,18 +902,22 @@ int _gnutls_handshake_buffer_get( GNUTLS_STATE state, char *data, int length)
state->gnutls_internals.handshake_hash_buffer.size -= length;
memcpy(data, state->gnutls_internals.handshake_hash_buffer.data, length);
/* overwrite buffer */
- memcpy(state->gnutls_internals.handshake_hash_buffer.data,
- &state->gnutls_internals.handshake_hash_buffer.data[length],
- state->gnutls_internals.handshake_hash_buffer.size);
- state->gnutls_internals.handshake_hash_buffer.data =
- gnutls_realloc_fast(state->gnutls_internals.handshake_hash_buffer.data,
- state->gnutls_internals.handshake_hash_buffer.size);
+
+ if (state->gnutls_internals.handshake_hash_buffer.size > 0) {
+ memmove(state->gnutls_internals.handshake_hash_buffer.data,
+ &state->gnutls_internals.handshake_hash_buffer.data[length],
+ state->gnutls_internals.handshake_hash_buffer.size);
- if (state->gnutls_internals.handshake_hash_buffer.data == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
+ state->gnutls_internals.handshake_hash_buffer.data =
+ gnutls_realloc_fast(state->gnutls_internals.handshake_hash_buffer.data,
+ state->gnutls_internals.handshake_hash_buffer.size);
+ if (state->gnutls_internals.handshake_hash_buffer.data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ }
+
return length;
}
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index bfc8d0a861..f4e4fef452 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001 Nikos Mavroyanopoulos
+ * Copyright (C) 2001,2002 Nikos Mavroyanopoulos
*
* This file is part of GNUTLS.
*
@@ -35,10 +35,6 @@
#include <gnutls_dh.h>
#include <gnutls_str.h>
-#ifdef DEBUG
-# warning MAX ALGORITHM PARAMS == 2, ok for RSA
-#endif
-
/* KX mappings to PK algorithms */
typedef struct {
KXAlgorithm kx_algorithm;
@@ -75,6 +71,29 @@ PKAlgorithm _gnutls_map_pk_get_pk(KXAlgorithm kx_algorithm)
return ret;
}
+/* this function reads an integer
+ * from asn1 structs. Combines the read and mpi_scan
+ * steps.
+ */
+static
+int _gnutls_x509_read_int( node_asn* node, char* value, char* tmpstr, int tmpstr_size, MPI* ret_mpi) {
+int len, result;
+
+ len = tmpstr_size - 1;
+ result = asn1_read_value(node, value, tmpstr, &len);
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if (_gnutls_mpi_scan( ret_mpi, tmpstr, &len) != 0) {
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ return 0;
+}
+
void gnutls_free_cert(gnutls_cert cert)
{
int n, i;
@@ -270,16 +289,27 @@ static int read_ca_mem(GNUTLS_X509PKI_CREDENTIALS res, const char *ca, int ca_si
/* Reads a PEM encoded PKCS-1 RSA private key from memory
+ * 2002-01-26: Added ability to read DSA keys.
*/
static int read_key_mem(GNUTLS_X509PKI_CREDENTIALS res, const char *key, int key_size)
{
int siz, ret;
opaque *b64;
gnutls_datum tmp;
+ PKAlgorithm pk;
/* read PKCS-1 private key */
siz = key_size;
+
+ /* If we find the "DSA PRIVATE" string in the
+ * pem encoded certificate then it's a DSA key.
+ */
+ if (strstr( key, "DSA PRIVATE")!=NULL)
+ pk = GNUTLS_PK_DSA;
+ else
+ pk = GNUTLS_PK_RSA;
+
siz = _gnutls_fbase64_decode(key, siz, &b64);
if (siz < 0) {
@@ -290,14 +320,27 @@ static int read_key_mem(GNUTLS_X509PKI_CREDENTIALS res, const char *key, int key
tmp.data = b64;
tmp.size = siz;
- if ((ret =
- _gnutls_pkcs1key2gnutlsKey(&res->pkey[res->ncerts],
- tmp)) < 0) {
- gnutls_assert();
- gnutls_free(b64);
- return ret;
+
+ switch (pk) { /* decode the key */
+ case GNUTLS_PK_RSA:
+ if ((ret =
+ _gnutls_PKCS1key2gnutlsKey(&res->pkey[res->ncerts],
+ tmp)) < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return ret;
+ }
+ break;
+ case GNUTLS_PK_DSA:
+ if ((ret =
+ _gnutls_DSAkey2gnutlsKey(&res->pkey[res->ncerts],
+ tmp)) < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return ret;
+ }
+ break;
}
-
gnutls_free(b64);
return 0;
@@ -413,6 +456,18 @@ int gnutls_x509pki_allocate_sc(GNUTLS_X509PKI_CREDENTIALS * res, int ncerts)
return 0;
}
+/* returns error if the certificate has different algorithm than
+ * the given key parameters.
+ */
+static int _gnutls_check_key_cert_match( GNUTLS_X509PKI_CREDENTIALS res) {
+ if (res->pkey->pk_algorithm != res->cert_list[0]->subject_pk_algorithm) {
+ gnutls_assert();
+ return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
+ }
+ return 0;
+}
+
+
/**
* gnutls_x509pki_set_key_file - Used to set keys in a GNUTLS_X509PKI_CREDENTIALS structure
* @res: is an &GNUTLS_X509PKI_CREDENTIALS structure.
@@ -425,7 +480,7 @@ int gnutls_x509pki_allocate_sc(GNUTLS_X509PKI_CREDENTIALS * res, int ncerts)
* more than once (in case multiple keys/certificates exist for the
* server).
*
- * Currently only PKCS-1 PEM encoded RSA private keys are accepted by
+ * Currently only PKCS-1 PEM encoded RSA and DSA private keys are accepted by
* this function.
*
**/
@@ -442,6 +497,11 @@ int gnutls_x509pki_set_key_file(GNUTLS_X509PKI_CREDENTIALS res, char *CERTFILE,
if ((ret = read_cert_file(res, CERTFILE)) < 0)
return ret;
+ if ((ret=_gnutls_check_key_cert_match( res)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
return 0;
}
@@ -575,18 +635,23 @@ int gnutls_x509pki_set_key_mem(GNUTLS_X509PKI_CREDENTIALS res, const gnutls_datu
if ((ret = read_cert_mem( res, CERT->data, CERT->size)) < 0)
return ret;
+ if ((ret=_gnutls_check_key_cert_match( res)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
return 0;
}
static int _read_rsa_params(opaque * der, int dersize, MPI * params)
{
- opaque str[MAX_X509_CERT_SIZE];
- int len, result;
+ opaque str[MAX_PARAMETER_SIZE];
+ int result;
node_asn *spk;
if (asn1_create_structure
- (_gnutls_get_pkcs(), "PKCS-1.RSAPublicKey", &spk,
+ (_gnutls_get_gnutls_asn(), "GNUTLS.RSAPublicKey", &spk,
"rsa_public_key") != ASN_OK) {
gnutls_assert();
return GNUTLS_E_ASN1_ERROR;
@@ -600,36 +665,83 @@ static int _read_rsa_params(opaque * der, int dersize, MPI * params)
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- len = sizeof(str) - 1;
- result = asn1_read_value(spk, "rsa_public_key.modulus", str, &len);
- if (result != ASN_OK) {
+
+ if ( (result=_gnutls_x509_read_int( spk, "rsa_public_key.modulus",
+ str, sizeof(str)-1, &params[0])) < 0) {
gnutls_assert();
asn1_delete_structure(spk);
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- if (_gnutls_mpi_scan(&params[0], str, &len) != 0) {
+ if ( (result=_gnutls_x509_read_int( spk, "rsa_public_key.publicExponent",
+ str, sizeof(str)-1, &params[1])) < 0) {
gnutls_assert();
+ _gnutls_mpi_release(&params[0]);
asn1_delete_structure(spk);
- return GNUTLS_E_MPI_SCAN_FAILED;
+ return GNUTLS_E_ASN1_PARSING_ERROR;
}
- len = sizeof(str) - 1;
- result =
- asn1_read_value(spk, "rsa_public_key.publicExponent", str,
- &len);
+ asn1_delete_structure(spk);
+
+ return 0;
+
+}
+
+
+/* reads p,q and g
+ * from the certificate
+ * params[0-2]
+ */
+static int _read_dsa_params(opaque * der, int dersize, MPI * params)
+{
+ opaque str[MAX_PARAMETER_SIZE];
+ int result;
+ node_asn *spk;
+
+ if (asn1_create_structure
+ (_gnutls_get_pkix(), "PKIX1Implicit88.Dss-Parms", &spk,
+ "dsa_parms") != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ result = asn1_get_der(spk, der, dersize);
+
if (result != ASN_OK) {
gnutls_assert();
- _gnutls_mpi_release(&params[0]);
asn1_delete_structure(spk);
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- if (_gnutls_mpi_scan(&params[1], str, &len) != 0) {
+ /* FIXME: If the parameters are not included in the certificate
+ * then the issuer's parameters should be used.
+ */
+
+ /* Read p */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.p", str, sizeof(str)-1, &params[0])) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* Read q */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.q", str, sizeof(str)-1, &params[1])) < 0) {
gnutls_assert();
+ asn1_delete_structure(spk);
_gnutls_mpi_release(&params[0]);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* Read g */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.g", str, sizeof(str)-1, &params[2])) < 0) {
+ gnutls_assert();
asn1_delete_structure(spk);
- return GNUTLS_E_MPI_SCAN_FAILED;
+ _gnutls_mpi_release(&params[0]);
+ _gnutls_mpi_release(&params[1]);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
}
asn1_delete_structure(spk);
@@ -638,6 +750,46 @@ static int _read_rsa_params(opaque * der, int dersize, MPI * params)
}
+/* reads DSA's Y
+ * from the certificate
+ * params[3]
+ */
+static int _read_dsa_pubkey(opaque * der, int dersize, MPI * params)
+{
+ opaque str[MAX_PARAMETER_SIZE];
+ int result;
+ node_asn *spk;
+
+ if ( (result=asn1_create_structure
+ (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &spk,
+ "dsa_public_key")) != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ result = asn1_get_der(spk, der, dersize);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* Read p */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_public_key", str, sizeof(str)-1, &params[3])) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ asn1_delete_structure(spk);
+
+ return 0;
+
+}
+
+
#define _READ(a, aa, b, c, d, e, res, f) \
result = _IREAD(a, aa, sizeof(aa), b, c, d, e, res, sizeof(res)-1, f); \
if (result<0) return result; \
@@ -898,9 +1050,113 @@ int _gnutls_get_version(node_asn * c2, char *root)
return (int) gversion[0] + 1;
}
-#ifdef DEBUG
-# warning FIX THIS FOR DSS
-#endif
+
+/* Extracts DSA and RSA parameters from a certificate.
+ */
+static
+int _gnutls_extract_cert_mpi_params( const char* ALGO_OID, gnutls_cert * gCert,
+ node_asn* c2, char* tmpstr, int tmpstr_size) {
+int len, result;
+
+ if (strcmp( ALGO_OID, "1 2 840 113549 1 1 1") == 0) { /* pkix-1 1 - RSA */
+ /* params[0] is the modulus,
+ * params[1] is the exponent
+ */
+ gCert->subject_pk_algorithm = GNUTLS_PK_RSA;
+
+ len = tmpstr_size - 1;
+ result =
+ asn1_read_value
+ (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
+ tmpstr, &len);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ((sizeof(gCert->params) / sizeof(MPI)) < RSA_PARAMS) {
+ gnutls_assert();
+ /* internal error. Increase the MPIs in params */
+ return GNUTLS_E_INTERNAL;
+ }
+
+ if ((result =
+ _read_rsa_params(tmpstr, len / 8, gCert->params)) < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+ }
+
+ if (strcmp( ALGO_OID, "1 2 840 10040 4 1") == 0) { /* pkix-1 1 - DSA */
+ /* params[0] is p,
+ * params[1] is q,
+ * params[2] is q,
+ * params[3] is pub.
+ */
+ gCert->subject_pk_algorithm = GNUTLS_PK_DSA;
+
+ len = tmpstr_size - 1;
+ result =
+ asn1_read_value
+ (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
+ tmpstr, &len);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ((sizeof(gCert->params) / sizeof(MPI)) < DSA_PARAMS) {
+ gnutls_assert();
+ /* internal error. Increase the MPIs in params */
+ return GNUTLS_E_INTERNAL;
+ }
+
+ if ((result =
+ _read_dsa_pubkey(tmpstr, len / 8, gCert->params)) < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Now read the parameters
+ */
+ len = tmpstr_size - 1;
+ result =
+ asn1_read_value
+ (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",
+ tmpstr, &len);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ((result =
+ _read_dsa_params(tmpstr, len, gCert->params)) < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+ }
+
+
+
+ /* other types like DH
+ * currently not supported
+ */
+ gnutls_assert();
+
+ _gnutls_log("CERT: ALGORITHM: %s\n", ALGO_OID);
+
+ gCert->subject_pk_algorithm = GNUTLS_PK_UNKNOWN;
+
+ return GNUTLS_E_INVALID_PARAMETERS;
+}
+
/* This function will convert a der certificate, to a format
* (structure) that gnutls can understand and use. Actually the
@@ -958,52 +1214,11 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert)
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- if (strcmp(str, "1 2 840 113549 1 1 1") == 0) { /* pkix-1 1 - RSA */
- /* params[0] is the modulus,
- * params[1] is the exponent
- */
- gCert->subject_pk_algorithm = GNUTLS_PK_RSA;
-
- len = sizeof(str) - 1;
- result =
- asn1_read_value
- (c2,
- "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
- str, &len);
-
- if (result != ASN_OK) {
- gnutls_assert();
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- if ((sizeof(gCert->params) / sizeof(MPI)) < 2) {
- gnutls_assert();
- /* internal error. Increase the MPIs in params */
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- return GNUTLS_E_UNKNOWN_ERROR;
- }
-
- if ((result =
- _read_rsa_params(str, len / 8, gCert->params)) < 0) {
- gnutls_assert();
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- return result;
- }
-
- } else {
- /* other types like DH, DSA
- * currently not supported
- */
+ if ( (result=_gnutls_extract_cert_mpi_params( str, gCert, c2, str, sizeof(str))) < 0) {
gnutls_assert();
-
- _gnutls_log("CERT: ALGORITHM: %s\n", str);
-
- gCert->subject_pk_algorithm = GNUTLS_PK_UNKNOWN;
-
+ asn1_delete_structure(c2);
+ gnutls_free_datum( &gCert->raw);
+ return result;
}
len = sizeof(gCert->signature);
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index b2ab12a3cd..a94854caf0 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -5,12 +5,30 @@
#include <x509_asn1.h>
#include <gnutls_ui.h>
-#define MAX_PARAMS_SIZE 2 /* ok for RSA */
+#define MAX_PARAMS_SIZE 5 /* ok for RSA and DSA */
+
+/* parameters should not be larger than this limit */
+#define MAX_PARAMETER_SIZE 1200
+#define DSA_PARAMS 5
+#define RSA_PARAMS 2
+
+#if MAX_PARAMS_SIZE - RSA_PARAMS < 0
+# error INCREASE RSA_PARAMS
+#endif
+
+#if MAX_PARAMS_SIZE - DSA_PARAMS < 0
+# error INCREASE DSA_PARAMS
+#endif
+
typedef struct gnutls_cert {
MPI params[MAX_PARAMS_SIZE]; /* the size of params depends on the public
* key algorithm
* RSA: [0] is modulus
* [1] is public exponent
+ * DSA: [0] is p
+ * [1] is q
+ * [2] is g
+ * [3] is pub
*/
PKAlgorithm subject_pk_algorithm;
@@ -39,6 +57,14 @@ typedef struct {
MPI params[MAX_PARAMS_SIZE];/* the size of params depends on the public
* key algorithm
*/
+ /*
+ * DSA: [0] is p
+ * [1] is q
+ * [2] is g
+ * [3] is Y (public)
+ * [4] is priv
+ */
+
PKAlgorithm pk_algorithm;
gnutls_datum raw; /* the raw key */
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 3a01bdf382..eafdb213e1 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -41,6 +41,7 @@ static gnutls_error_entry error_algorithms[] = {
GNUTLS_ERROR_ENTRY( GNUTLS_E_MAC_FAILED, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_CIPHER, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_CIPHER_SUITE, 1),
+ GNUTLS_ERROR_ENTRY( GNUTLS_E_CERTIFICATE_KEY_MISMATCH, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_MAC_ALGORITHM, 1),
GNUTLS_ERROR_ENTRY( GNUTLS_E_UNKNOWN_ERROR, 1),
diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h
index ba7686ae75..6b1d64ea11 100644
--- a/lib/gnutls_errors_int.h
+++ b/lib/gnutls_errors_int.h
@@ -58,8 +58,9 @@
#define GNUTLS_E_ILLEGAL_PARAMETER -55 /* GNUTLS_A_ILLEGAL_PARAMETER */
#define GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE -56
#define GNUTLS_E_PKCS1_WRONG_PAD -57
-#define GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION -57
-#define GNUTLS_E_INTERNAL -58
+#define GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION -58
+#define GNUTLS_E_INTERNAL -59
+#define GNUTLS_E_CERTIFICATE_KEY_MISMATCH -60
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -250
diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index fb495c4729..47ef73f2ef 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -161,7 +161,6 @@ static void _gnutls_extension_list_add( GNUTLS_STATE state, uint8 type) {
} else {
#ifdef DEBUG
_gnutls_log("EXT: Increase MAX_EXT_TYPES\n");
- exit(1);
#endif
}
}
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index 019d57db1b..50acbf63ed 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -25,7 +25,7 @@
/* created by asn1c */
-extern const static_asn pkcs1_asn1_tab[];
+extern const static_asn gnutls_asn1_tab[];
extern const static_asn pkix_asn1_tab[];
@@ -35,14 +35,14 @@ typedef void (*LOG_FUNC)( const char*);
LOG_FUNC _gnutls_log_func;
static node_asn *PKIX1_ASN;
-static node_asn *PKCS1_ASN;
+static node_asn *GNUTLS_ASN;
node_asn* _gnutls_get_pkix(void) {
return PKIX1_ASN;
}
-node_asn* _gnutls_get_pkcs(void) {
- return PKCS1_ASN;
+node_asn* _gnutls_get_gnutls_asn(void) {
+ return GNUTLS_ASN;
}
@@ -108,7 +108,7 @@ int gnutls_global_init( void)
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- result=asn1_create_tree( (void*)pkcs1_asn1_tab, &PKCS1_ASN);
+ result=asn1_create_tree( (void*)gnutls_asn1_tab, &GNUTLS_ASN);
if (result != ASN_OK) {
asn1_delete_structure( PKIX1_ASN);
return GNUTLS_E_PARSING_ERROR;
@@ -135,7 +135,7 @@ void gnutls_global_deinit( void) {
_gnutls_init--;
if (_gnutls_init==0) {
- asn1_delete_structure( PKCS1_ASN);
+ asn1_delete_structure( GNUTLS_ASN);
asn1_delete_structure( PKIX1_ASN);
_gnutls_dh_clear_mpis();
diff --git a/lib/gnutls_global.h b/lib/gnutls_global.h
index c767b45f96..6361efb781 100644
--- a/lib/gnutls_global.h
+++ b/lib/gnutls_global.h
@@ -4,7 +4,7 @@
#include <x509_asn1.h>
int gnutls_is_secure_memory(const void* mem);
-node_asn* _gnutls_get_pkcs(void);
+node_asn* _gnutls_get_gnutls_asn(void);
node_asn* _gnutls_get_pkix(void);
#endif
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 1b8a2ff070..785d40d315 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -359,7 +359,11 @@ opaque * data;
/* We check if there are pending data to hash.
*/
siz = _gnutls_handshake_buffer_get_size(state);
-
+ if (siz < 0) {
+ gnutls_assert();
+ return siz;
+ }
+
if (siz > 0) { /* if there are data to hash */
data = gnutls_malloc(siz);
if (data == NULL) {
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 7a47d88d7b..631997ac8e 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -31,9 +31,9 @@
#define WRITE_DEBUG
#define READ_DEBUG
#define HANDSHAKE_DEBUG // Prints some information on handshake
-#define RECORD_DEBUG
+#define RECORD_DEBUG*/
#define DEBUG
-*/
+
/* It might be a good idea to replace int with void*
* here.
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;
+}
diff --git a/lib/gnutls_pk.h b/lib/gnutls_pk.h
index dc11a5a7ea..95a54f4ee3 100644
--- a/lib/gnutls_pk.h
+++ b/lib/gnutls_pk.h
@@ -8,7 +8,11 @@ typedef enum PKAlgorithm { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA, /* sign only */
int _gnutls_pk_encrypt(int algo, MPI * resarr, MPI data, MPI ** pkey);
int _gnutls_pkcs1_rsa_encrypt(gnutls_datum * ciphertext, gnutls_datum plaintext,
MPI pkey, MPI n, int btype);
+int _gnutls_dsa_sign(gnutls_datum * signature, gnutls_datum plaintext,
+ MPI p, MPI q, MPI g, MPI Y);
int _gnutls_pkcs1_rsa_decrypt(gnutls_datum * plaintext, gnutls_datum ciphertext,
MPI pkey, MPI n, int btype);
+int _gnutls_rsa_verify( const gnutls_datum* vdata, const gnutls_datum *ciphertext,
+ MPI pkey, MPI n, int btype);
#endif /* GNUTLS_PK_H */
diff --git a/lib/gnutls_privkey.c b/lib/gnutls_privkey.c
index 3501944ede..ac749ed47b 100644
--- a/lib/gnutls_privkey.c
+++ b/lib/gnutls_privkey.c
@@ -30,29 +30,30 @@
#include <gnutls_gcry.h>
#include <gnutls_global.h>
+
/* Converts an RSA PKCS#1 key to
* an internal structure (gnutls_private_key)
*/
-int _gnutls_pkcs1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum cert) {
+int _gnutls_PKCS1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key) {
int result;
- opaque str[MAX_X509_CERT_SIZE];
+ opaque str[MAX_PARAMETER_SIZE];
int len = sizeof(str);
node_asn *pkcs_asn;
pkey->pk_algorithm = GNUTLS_PK_RSA;
- if (asn1_create_structure( _gnutls_get_pkcs(), "PKCS-1.RSAPrivateKey", &pkcs_asn, "rsakey")!=ASN_OK) {
+ if (asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.RSAPrivateKey", &pkcs_asn, "rsakey")!=ASN_OK) {
gnutls_assert();
return GNUTLS_E_ASN1_ERROR;
}
- if ((sizeof( pkey->params)/sizeof(MPI)) < 2) {
+ if ((sizeof( pkey->params)/sizeof(MPI)) < RSA_PARAMS) {
gnutls_assert();
/* internal error. Increase the MPIs in params */
- return GNUTLS_E_UNKNOWN_ERROR;
+ return GNUTLS_E_INTERNAL;
}
- result = asn1_get_der( pkcs_asn, cert.data, cert.size);
+ result = asn1_get_der( pkcs_asn, raw_key.data, raw_key.size);
if (result != ASN_OK) {
gnutls_assert();
return GNUTLS_E_ASN1_PARSING_ERROR;
@@ -94,9 +95,149 @@ int _gnutls_pkcs1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum cert) {
asn1_delete_structure(pkcs_asn);
- if (gnutls_set_datum( &pkey->raw, cert.data, cert.size) < 0) {
+ if (gnutls_set_datum( &pkey->raw, raw_key.data, raw_key.size) < 0) {
+ _gnutls_mpi_release(&pkey->params[0]);
+ _gnutls_mpi_release(&pkey->params[1]);
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+
+
+}
+
+int _gnutls_DSAkey2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key) {
+ int result;
+ opaque str[MAX_PARAMETER_SIZE];
+ int len = sizeof(str);
+ node_asn *pkix_asn;
+
+ pkey->pk_algorithm = GNUTLS_PK_DSA;
+
+ if (asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.DSAPrivateKey", &pkix_asn, "dsakey")!=ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ if ((sizeof( pkey->params)/sizeof(MPI)) < DSA_PARAMS) {
+ gnutls_assert();
+ /* internal error. Increase the MPIs in params */
+ return GNUTLS_E_INTERNAL;
+ }
+
+ result = asn1_get_der( pkix_asn, raw_key.data, raw_key.size);
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ len = sizeof(str) - 1;
+ result =
+ asn1_read_value( pkix_asn, "dsakey.p", str, &len);
+ if (result != ASN_OK) {
+ gnutls_assert();
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if (_gnutls_mpi_scan( &pkey->params[0], /* p */
+ str, &len) != 0) {
+ gnutls_assert();
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ len = sizeof(str) - 1;
+ result =
+ asn1_read_value( pkix_asn, "dsakey.q", str, &len);
+ if (result != ASN_OK) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if (_gnutls_mpi_scan( &pkey->params[1], /* q */ str, &len) != 0) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ len = sizeof(str) - 1;
+ result =
+ asn1_read_value( pkix_asn, "dsakey.g", str, &len);
+ if (result != ASN_OK) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ _gnutls_mpi_release(&pkey->params[1]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if (_gnutls_mpi_scan( &pkey->params[2], /* g */ str, &len) != 0) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ _gnutls_mpi_release(&pkey->params[1]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ len = sizeof(str) - 1;
+ result =
+ asn1_read_value( pkix_asn, "dsakey.Y", str, &len);
+ if (result != ASN_OK) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ _gnutls_mpi_release(&pkey->params[1]);
+ _gnutls_mpi_release(&pkey->params[2]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if (_gnutls_mpi_scan( &pkey->params[3], /* priv key */
+ str, &len) != 0) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ _gnutls_mpi_release(&pkey->params[1]);
+ _gnutls_mpi_release(&pkey->params[2]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ len = sizeof(str) - 1;
+ result =
+ asn1_read_value( pkix_asn, "dsakey.priv", str, &len);
+ if (result != ASN_OK) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ _gnutls_mpi_release(&pkey->params[1]);
+ _gnutls_mpi_release(&pkey->params[2]);
+ _gnutls_mpi_release(&pkey->params[3]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if (_gnutls_mpi_scan( &pkey->params[4], /* priv key */
+ str, &len) != 0) {
+ gnutls_assert();
+ _gnutls_mpi_release(&pkey->params[0]);
+ _gnutls_mpi_release(&pkey->params[1]);
+ _gnutls_mpi_release(&pkey->params[2]);
+ _gnutls_mpi_release(&pkey->params[3]);
+ asn1_delete_structure(pkix_asn);
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ asn1_delete_structure(pkix_asn);
+
+ if (gnutls_set_datum( &pkey->raw, raw_key.data, raw_key.size) < 0) {
_gnutls_mpi_release(&pkey->params[0]);
_gnutls_mpi_release(&pkey->params[1]);
+ _gnutls_mpi_release(&pkey->params[2]);
+ _gnutls_mpi_release(&pkey->params[3]);
+ _gnutls_mpi_release(&pkey->params[4]);
gnutls_assert();
return GNUTLS_E_MEMORY_ERROR;
}
diff --git a/lib/gnutls_privkey.h b/lib/gnutls_privkey.h
index 244c3084d1..4e045a01b6 100644
--- a/lib/gnutls_privkey.h
+++ b/lib/gnutls_privkey.h
@@ -1,2 +1,3 @@
-int _gnutls_pkcs1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum cert);
+int _gnutls_PKCS1key2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key);
+int _gnutls_DSAkey2gnutlsKey(gnutls_private_key * pkey, gnutls_datum raw_key);
void _gnutls_free_private_key( gnutls_private_key pkey);
diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c
index 313cf6b226..a2502705f6 100644
--- a/lib/gnutls_sig.c
+++ b/lib/gnutls_sig.c
@@ -65,12 +65,10 @@ GNUTLS_MAC_HANDLE td_sha;
dconcat.data = concat;
dconcat.size = 36;
- ret = _gnutls_pkcs1_rsa_generate_sig( cert, pkey, &dconcat, signature);
- if (ret < 0) {
+ ret = _gnutls_generate_sig( cert, pkey, &dconcat, signature);
+ if (ret < 0)
gnutls_assert();
- return ret;
- }
-
+
return ret;
}
@@ -113,23 +111,20 @@ opaque concat[36];
dconcat.data = concat;
dconcat.size = 36;
- ret = _gnutls_pkcs1_rsa_generate_sig( cert, pkey, &dconcat, signature);
-
- if (ret < 0) {
+ ret = _gnutls_generate_sig( cert, pkey, &dconcat, signature);
+ if (ret < 0)
gnutls_assert();
- return ret;
- }
-
+
return ret;
}
-/* This will create a PKCS1 signature, as defined in the TLS protocol.
+/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
* Cert is the certificate of the corresponding private key. It is only checked if
* it supports signing.
*/
-int _gnutls_pkcs1_rsa_generate_sig( gnutls_cert* cert, gnutls_private_key *pkey, const gnutls_datum* hash_concat, gnutls_datum *signature)
+int _gnutls_generate_sig( gnutls_cert* cert, gnutls_private_key *pkey, const gnutls_datum* hash_concat, gnutls_datum *signature)
{
int ret;
gnutls_datum tmpdata;
@@ -146,10 +141,28 @@ gnutls_datum tmpdata;
switch(pkey->pk_algorithm) {
case GNUTLS_PK_RSA:
-
tmpdata.data = hash_concat->data;
tmpdata.size = hash_concat->size; /* md5 + sha */
+ /* encrypt */
+ if ((ret=_gnutls_pkcs1_rsa_encrypt( signature, tmpdata, pkey->params[0], pkey->params[1], 1)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ break;
+ case GNUTLS_PK_DSA:
+ /* Ok this is silly. We have calculated
+ * md5 also!
+ */
+ tmpdata.data = &hash_concat->data[16];
+ tmpdata.size = 20; /* sha */
+
+ /* sign */
+ if ((ret=_gnutls_dsa_sign( signature, tmpdata, pkey->params[0], pkey->params[1], pkey->params[2], pkey->params[3])) < 0) {
+ gnutls_assert();
+ return ret;
+ }
break;
default:
gnutls_assert();
@@ -158,18 +171,15 @@ gnutls_datum tmpdata;
}
- /* encrypt der */
- if ( (ret=_gnutls_pkcs1_rsa_encrypt( signature, tmpdata, pkey->params[0], pkey->params[1], 1)) < 0) {
- gnutls_assert();
- return ret;
- }
return 0;
}
+
+
int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert *cert, const gnutls_datum *hash_concat, gnutls_datum *signature) {
int ret;
- gnutls_datum plain, vdata;
+ gnutls_datum vdata;
if (cert->version == 0 || cert==NULL) { /* this is the only way to check
* if it is initialized
@@ -193,30 +203,32 @@ int _gnutls_pkcs1_rsa_verify_sig( gnutls_cert *cert, const gnutls_datum *hash_co
vdata.data = hash_concat->data;
vdata.size = hash_concat->size;
+ /* verify signature */
+ if ( (ret=_gnutls_rsa_verify( &vdata, signature, cert->params[1], cert->params[0], 1)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ break;
+ case GNUTLS_PK_DSA:
+
+ vdata.data = &hash_concat->data[16];
+ vdata.size = 20; /* sha1 */
+
+ /* decrypt signature */
+ if ( (ret=_gnutls_dsa_verify( &vdata, *signature, cert->params[0],
+ cert->params[1], cert->params[2], cert->params[3])) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
break;
default:
gnutls_assert();
return GNUTLS_E_UNIMPLEMENTED_FEATURE;
}
- /* decrypt signature */
- if ( (ret=_gnutls_pkcs1_rsa_decrypt( &plain, *signature, cert->params[1], cert->params[0], 1)) < 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;
}
diff --git a/lib/pkix.asn b/lib/pkix.asn
index 183345e523..9faab3a370 100644
--- a/lib/pkix.asn
+++ b/lib/pkix.asn
@@ -613,9 +613,10 @@ sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
id-dsa-with-sha1 OBJECT IDENTIFIER ::= {
iso(1) member-body(2) us(840) x9-57 (10040) x9algorithm(4) 3 }
-Dss-Sig-Value ::= SEQUENCE {
+Dss-Sig-Value ::= SEQUENCE {
r INTEGER,
- s INTEGER }
+ s INTEGER
+}
dhpublicnumber OBJECT IDENTIFIER ::= {
iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1 }
diff --git a/lib/x509_sig_check.c b/lib/x509_sig_check.c
index e6f1d7f3ab..1556ed1114 100644
--- a/lib/x509_sig_check.c
+++ b/lib/x509_sig_check.c
@@ -81,7 +81,7 @@ int result;
opaque str[1024];
int len;
- if (asn1_create_structure( _gnutls_get_pkcs(), "PKCS-1.DigestInfo", &dinfo, "digest_info")!=ASN_OK) {
+ if (asn1_create_structure( _gnutls_get_gnutls_asn(), "GNUTLS.DigestInfo", &dinfo, "digest_info")!=ASN_OK) {
gnutls_assert();
return GNUTLS_E_ASN1_ERROR;
}
@@ -182,6 +182,13 @@ _pkcs1_rsa_verify_sig( gnutls_datum* signature, gnutls_datum* text, MPI e, MPI m
return 0;
}
+#ifdef DEBUG
+/* This is for CA DSS params - can wait */
+# warning CHECK HERE FOR DSS
+#endif
+
+/* verifies if the certificate is properly signed.
+ */
CertificateStatus gnutls_x509_verify_signature(gnutls_cert* cert, gnutls_cert* issuer) {
gnutls_datum signature;
gnutls_datum tbs;
@@ -218,8 +225,8 @@ static int _gnutls_digestinfo_encode( opaque* data, int data_size, char* OID, gn
node_asn *di;
int result;
- if (asn1_create_structure( _gnutls_get_pkcs(),
- "PKCS-1.DigestInfo", &di, "di") != ASN_OK) {
+ if (asn1_create_structure( _gnutls_get_gnutls_asn(),
+ "GNUTLS.DigestInfo", &di, "di") != ASN_OK) {
gnutls_assert();
return GNUTLS_E_ASN1_ERROR;
}