diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-05-18 23:18:07 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2010-06-03 19:42:02 +0200 |
commit | 68b714494d6b99104897738ccec676a81be7a35d (patch) | |
tree | dc0f04569bc144dec9120bd423fedb306c70ff23 /lib/x509 | |
parent | 4d8be74bbc3b60f539bff11a20544d80339ff34f (diff) | |
download | gnutls-68b714494d6b99104897738ccec676a81be7a35d.tar.gz |
Added operations to sign CRLs, certificates and requests with an abstract key and thus with a PKCS #11 key as well.
Diffstat (limited to 'lib/x509')
-rw-r--r-- | lib/x509/crl_write.c | 74 | ||||
-rw-r--r-- | lib/x509/crq.c | 143 | ||||
-rw-r--r-- | lib/x509/mpi.c | 3 | ||||
-rw-r--r-- | lib/x509/sign.c | 39 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 12 | ||||
-rw-r--r-- | lib/x509/x509_write.c | 75 |
6 files changed, 269 insertions, 77 deletions
diff --git a/lib/x509/crl_write.c b/lib/x509/crl_write.c index d355c4f351..c9c784d0aa 100644 --- a/lib/x509/crl_write.c +++ b/lib/x509/crl_write.c @@ -101,6 +101,7 @@ gnutls_x509_crl_sign2 (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer, gnutls_digest_algorithm_t dig, unsigned int flags) { int result; + gnutls_privkey_t privkey; if (crl == NULL || issuer == NULL) { @@ -108,19 +109,33 @@ gnutls_x509_crl_sign2 (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer, return GNUTLS_E_INVALID_REQUEST; } - /* disable all the unneeded OPTIONAL fields. - */ - disable_optional_stuff (crl); - - result = _gnutls_x509_pkix_sign (crl->crl, "tbsCertList", - dig, issuer, issuer_key); + result = gnutls_privkey_init(&privkey); if (result < 0) { gnutls_assert (); return result; } - return 0; + result = gnutls_privkey_import_x509(privkey, issuer_key, 0); + if (result < 0) + { + gnutls_assert (); + goto fail; + } + + result = gnutls_x509_crl_privkey_sign (crl, issuer, privkey, dig, flags); + if (result < 0) + { + gnutls_assert (); + goto fail; + } + + result = 0; + +fail: + gnutls_privkey_deinit(privkey); + + return result; } /** @@ -441,4 +456,49 @@ gnutls_x509_crl_set_number (gnutls_x509_crl_t crl, return 0; } +/** + * gnutls_x509_crl_privkey_sign: + * @crl: should contain a gnutls_x509_crl_t structure + * @issuer: is the certificate of the certificate issuer + * @issuer_key: holds the issuer's private key + * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. + * @flags: must be 0 + * + * This function will sign the CRL with the issuer's private key, and + * will copy the issuer's information into the CRL. + * + * This must be the last step in a certificate CRL since all + * the previously set parameters are now signed. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_x509_crl_privkey_sign (gnutls_x509_crl_t crl, gnutls_x509_crt_t issuer, + gnutls_privkey_t issuer_key, + gnutls_digest_algorithm_t dig, unsigned int flags) +{ + int result; + + if (crl == NULL || issuer == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + /* disable all the unneeded OPTIONAL fields. + */ + disable_optional_stuff (crl); + + result = _gnutls_x509_pkix_sign (crl->crl, "tbsCertList", + dig, issuer, issuer_key); + if (result < 0) + { + gnutls_assert (); + return result; + } + + return 0; +} + #endif /* ENABLE_PKI */ diff --git a/lib/x509/crq.c b/lib/x509/crq.c index 6a9113b9b1..e18578f99b 100644 --- a/lib/x509/crq.c +++ b/lib/x509/crq.c @@ -1010,7 +1010,7 @@ gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key, gnutls_digest_algorithm_t dig, unsigned int flags) { int result; - gnutls_datum_t signature; + gnutls_privkey_t privkey; if (crq == NULL) { @@ -1018,55 +1018,33 @@ gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key, return GNUTLS_E_INVALID_REQUEST; } - /* Make sure version field is set. */ - if (gnutls_x509_crq_get_version (crq) == GNUTLS_E_ASN1_VALUE_NOT_FOUND) - { - result = gnutls_x509_crq_set_version (crq, 1); - if (result < 0) - { - gnutls_assert (); - return result; - } - } - - /* Step 1. Self sign the request. - */ - result = - _gnutls_x509_sign_tbs (crq->crq, "certificationRequestInfo", - dig, key, &signature); - + result = gnutls_privkey_init(&privkey); if (result < 0) { gnutls_assert (); return result; } - /* Step 2. write the signature (bits) - */ - result = - asn1_write_value (crq->crq, "signature", signature.data, - signature.size * 8); - - _gnutls_free_datum (&signature); - - if (result != ASN1_SUCCESS) + result = gnutls_privkey_import_x509(privkey, key, 0); + if (result < 0) { gnutls_assert (); - return _gnutls_asn2err (result); + goto fail; } - /* Step 3. Write the signatureAlgorithm field. - */ - result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm", - key->pk_algorithm, dig, key->params, - key->params_size); + result = gnutls_x509_crq_privkey_sign (crq, privkey, dig, flags); if (result < 0) { gnutls_assert (); - return result; + goto fail; } - return 0; + result = 0; + +fail: + gnutls_privkey_deinit(privkey); + + return result; } /** @@ -2445,5 +2423,100 @@ gnutls_x509_crq_get_key_id (gnutls_x509_crq_t crq, unsigned int flags, return result; } +/** + * gnutls_x509_crq_privkey_sign: + * @crq: should contain a #gnutls_x509_crq_t structure + * @key: holds a private key + * @dig: The message digest to use, i.e., %GNUTLS_DIG_SHA1 + * @flags: must be 0 + * + * This function will sign the certificate request with a private key. + * This must be the same key as the one used in + * gnutls_x509_crt_set_key() since a certificate request is self + * signed. + * + * This must be the last step in a certificate request generation + * since all the previously set parameters are now signed. + * + * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error. + * %GNUTLS_E_ASN1_VALUE_NOT_FOUND is returned if you didn't set all + * information in the certificate request (e.g., the version using + * gnutls_x509_crq_set_version()). + * + **/ +int +gnutls_x509_crq_privkey_sign (gnutls_x509_crq_t crq, gnutls_privkey_t key, + gnutls_digest_algorithm_t dig, unsigned int flags) +{ + int result; + gnutls_datum_t signature; + gnutls_datum_t tbs; + + if (crq == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + /* Make sure version field is set. */ + if (gnutls_x509_crq_get_version (crq) == GNUTLS_E_ASN1_VALUE_NOT_FOUND) + { + result = gnutls_x509_crq_set_version (crq, 1); + if (result < 0) + { + gnutls_assert (); + return result; + } + } + + /* Step 1. Self sign the request. + */ + result = + _gnutls_x509_get_tbs (crq->crq, "certificationRequestInfo", + &tbs); + + if (result < 0) + { + gnutls_assert (); + return result; + } + + result = gnutls_privkey_sign_data (key, dig, 0, &tbs, &signature); + gnutls_free(tbs.data); + + if (result < 0) + { + gnutls_assert (); + return result; + } + + /* Step 2. write the signature (bits) + */ + result = + asn1_write_value (crq->crq, "signature", signature.data, + signature.size * 8); + + _gnutls_free_datum (&signature); + + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + return _gnutls_asn2err (result); + } + + /* Step 3. Write the signatureAlgorithm field. + */ + result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm", + gnutls_privkey_get_pk_algorithm(key, NULL), dig); + if (result < 0) + { + gnutls_assert (); + return result; + } + + return 0; +} + + #endif /* ENABLE_PKI */ diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c index 76747f251c..7b4e7d4596 100644 --- a/lib/x509/mpi.c +++ b/lib/x509/mpi.c @@ -422,8 +422,7 @@ cleanup: int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, - gnutls_digest_algorithm_t dig, - bigint_t * params, int params_size) + gnutls_digest_algorithm_t dig) { int result; char name[128]; diff --git a/lib/x509/sign.c b/lib/x509/sign.c index f272c08e6f..31c7c4f579 100644 --- a/lib/x509/sign.c +++ b/lib/x509/sign.c @@ -42,6 +42,7 @@ #include <x509_int.h> #include <common.h> #include <sign.h> +#include <gnutls/abstract.h> /* Writes the digest information and the digest in a DER encoded * structure. The digest info is allocated and stored into the info structure. @@ -199,15 +200,12 @@ pk_dsa_hash (const gnutls_datum_t * text, gnutls_datum_t * hash) * of the TBS and sign it on the fly. */ int -_gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name, - gnutls_digest_algorithm_t hash, - gnutls_x509_privkey_t signer, - gnutls_datum_t * signature) +_gnutls_x509_get_tbs (ASN1_TYPE cert, const char *tbs_name, + gnutls_datum_t * tbs) { int result; opaque *buf; int buf_size; - gnutls_datum_t tbs; buf_size = 0; asn1_der_coding (cert, tbs_name, NULL, &buf_size, NULL); @@ -228,13 +226,10 @@ _gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name, return _gnutls_asn2err (result); } - tbs.data = buf; - tbs.size = buf_size; - - result = gnutls_x509_privkey_sign_data2 (signer, hash, 0, &tbs, signature); - gnutls_free (buf); + tbs->data = buf; + tbs->size = buf_size; - return result; + return 0; } /*- @@ -253,10 +248,11 @@ int _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, gnutls_digest_algorithm_t dig, gnutls_x509_crt_t issuer, - gnutls_x509_privkey_t issuer_key) + gnutls_privkey_t issuer_key) { int result; gnutls_datum_t signature; + gnutls_datum_t tbs; char name[128]; /* Step 1. Copy the issuer's name into the certificate. @@ -277,9 +273,7 @@ _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, _gnutls_str_cat (name, sizeof (name), ".signature"); result = _gnutls_x509_write_sig_params (src, name, - issuer_key->pk_algorithm, dig, - issuer_key->params, - issuer_key->params_size); + gnutls_privkey_get_pk_algorithm(issuer_key, NULL), dig); if (result < 0) { gnutls_assert (); @@ -288,7 +282,16 @@ _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, /* Step 2. Sign the certificate. */ - result = _gnutls_x509_sign_tbs (src, src_name, dig, issuer_key, &signature); + result = _gnutls_x509_get_tbs (src, src_name, &tbs); + + if (result < 0) + { + gnutls_assert (); + return result; + } + + result = gnutls_privkey_sign_data (issuer_key, dig, 0, &tbs, &signature); + gnutls_free(tbs.data); if (result < 0) { @@ -314,9 +317,7 @@ _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, */ result = _gnutls_x509_write_sig_params (src, "signatureAlgorithm", - issuer_key->pk_algorithm, dig, - issuer_key->params, - issuer_key->params_size); + gnutls_privkey_get_pk_algorithm(issuer_key, NULL), dig); if (result < 0) { gnutls_assert (); diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index ede4814bac..ea68d59d23 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -27,6 +27,7 @@ # define X509_H #include <gnutls/x509.h> +#include <gnutls/abstract.h> #include <libtasn1.h> @@ -134,14 +135,12 @@ int _gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl, gnutls_datum_t * dn); /* sign.c */ -int _gnutls_x509_sign_tbs (ASN1_TYPE cert, const char *tbs_name, - gnutls_digest_algorithm_t hash, - gnutls_x509_privkey_t signer, - gnutls_datum_t * signature); +int _gnutls_x509_get_tbs (ASN1_TYPE cert, const char *tbs_name, + gnutls_datum_t * tbs); int _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, gnutls_digest_algorithm_t, gnutls_x509_crt_t issuer, - gnutls_x509_privkey_t issuer_key); + gnutls_privkey_t issuer_key); /* dn.c */ #define OID_X520_COUNTRY_NAME "2.5.4.6" @@ -303,8 +302,7 @@ int _gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value, int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, - gnutls_digest_algorithm_t, - bigint_t * params, int params_size); + gnutls_digest_algorithm_t); /* pkcs12.h */ #include <gnutls/pkcs12.h> diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c index f65e7af96b..dc47af20c3 100644 --- a/lib/x509/x509_write.c +++ b/lib/x509/x509_write.c @@ -752,6 +752,7 @@ gnutls_x509_crt_sign2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, gnutls_digest_algorithm_t dig, unsigned int flags) { int result; + gnutls_privkey_t privkey; if (crt == NULL || issuer == NULL || issuer_key == NULL) { @@ -759,19 +760,33 @@ gnutls_x509_crt_sign2 (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, return GNUTLS_E_INVALID_REQUEST; } - /* disable all the unneeded OPTIONAL fields. - */ - disable_optional_stuff (crt); - - result = _gnutls_x509_pkix_sign (crt->cert, "tbsCertificate", - dig, issuer, issuer_key); + result = gnutls_privkey_init(&privkey); if (result < 0) { gnutls_assert (); return result; } - return 0; + result = gnutls_privkey_import_x509(privkey, issuer_key, 0); + if (result < 0) + { + gnutls_assert (); + goto fail; + } + + result = gnutls_x509_crt_privkey_sign (crt, issuer, privkey, dig, flags); + if (result < 0) + { + gnutls_assert (); + goto fail; + } + + result = 0; + +fail: + gnutls_privkey_deinit(privkey); + + return result; } /** @@ -1279,4 +1294,50 @@ gnutls_x509_crt_set_key_purpose_oid (gnutls_x509_crt_t cert, } +/** + * gnutls_x509_crt_privkey_sign: + * @crt: a certificate of type #gnutls_x509_crt_t + * @issuer: is the certificate of the certificate issuer + * @issuer_key: holds the issuer's private key + * @dig: The message digest to use, %GNUTLS_DIG_SHA1 is a safe choice + * @flags: must be 0 + * + * This function will sign the certificate with the issuer's private key, and + * will copy the issuer's information into the certificate. + * + * This must be the last step in a certificate generation since all + * the previously set parameters are now signed. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_x509_crt_privkey_sign (gnutls_x509_crt_t crt, gnutls_x509_crt_t issuer, + gnutls_privkey_t issuer_key, + gnutls_digest_algorithm_t dig, unsigned int flags) +{ + int result; + + if (crt == NULL || issuer == NULL || issuer_key == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + /* disable all the unneeded OPTIONAL fields. + */ + disable_optional_stuff (crt); + + result = _gnutls_x509_pkix_sign (crt->cert, "tbsCertificate", + dig, issuer, issuer_key); + if (result < 0) + { + gnutls_assert (); + return result; + } + + return 0; +} + + #endif /* ENABLE_PKI */ |