From: Nikos Mavrogiannopoulos Date: Sat, 4 Oct 2008 08:37:42 +0000 (+0300) Subject: Added gnutls_x509_crq_set_key_purpose_oid and gnutls_x509_crq_get_key_purpose_oid. X-Git-Tag: gnutls_2_7_0~49 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=609244d4cb86df7e5f9e174e012fdb247644bbfd;p=thirdparty%2Fgnutls.git Added gnutls_x509_crq_set_key_purpose_oid and gnutls_x509_crq_get_key_purpose_oid. --- diff --git a/NEWS b/NEWS index 3b3cbe99e4..0c65d5a910 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,8 @@ gnutls_x509_crq_get_subject_alt_othername_oid: ADDED gnutls_x509_crq_set_basic_constraints: ADDED gnutls_x509_crq_set_key_usage: ADDED gnutls_x509_crq_set_subject_alt_name: ADDED +gnutls_x509_crq_set_key_purpose_oid: ADDED +gnutls_x509_crq_get_key_purpose_oid: ADDED * Version 2.5.9 (released 2008-09-29) diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h index ee6e937cb4..aaee2d5629 100644 --- a/includes/gnutls/x509.h +++ b/includes/gnutls/x509.h @@ -717,6 +717,11 @@ extern "C" int gnutls_x509_crq_set_key_usage (gnutls_x509_crq_t crq, unsigned int usage); int gnutls_x509_crq_set_basic_constraints (gnutls_x509_crq_t crq, unsigned int ca, int pathLenConstraint); + int gnutls_x509_crq_set_key_purpose_oid (gnutls_x509_crq_t cert, + const void *oid, unsigned int critical); + int gnutls_x509_crq_get_key_purpose_oid (gnutls_x509_crq_t cert, + int indx, void *oid, size_t * sizeof_oid, + unsigned int *critical); int gnutls_x509_crq_get_extension_data (gnutls_x509_crq_t cert, int indx, void *data, size_t * sizeof_data); diff --git a/lib/x509/crq.c b/lib/x509/crq.c index 0db1b370c8..df8de478ba 100644 --- a/lib/x509/crq.c +++ b/lib/x509/crq.c @@ -524,6 +524,7 @@ overwrite_attribute (ASN1_TYPE asn, const char* root, unsigned int indx, return result; } + return 0; } @@ -626,7 +627,7 @@ gnutls_x509_crq_set_attribute_by_oid (gnutls_x509_crq_t crq, size_t sizeof_buf) { int result; - gnutls_datum data = {buf, sizeof_buf}; + gnutls_datum data = { buf, sizeof_buf }; if (crq == NULL) { @@ -1361,7 +1362,6 @@ gnutls_x509_crq_get_extension_info (gnutls_x509_crq_t cert, int indx, if (result == ASN1_ELEMENT_NOT_FOUND) { asn1_delete_structure (&c2); - gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } else if (result < 0) @@ -1963,4 +1963,233 @@ gnutls_x509_crq_set_key_usage (gnutls_x509_crq_t crq, unsigned int usage) return 0; } +/** + * gnutls_x509_crq_get_key_purpose_oid - This function returns the Certificate's key purpose OIDs + * @cert: should contain a #gnutls_x509_crq_t structure + * @indx: This specifies which OID to return. Use zero to get the first one. + * @oid: a pointer to a buffer to hold the OID (may be null) + * @sizeof_oid: initially holds the size of @oid + * + * This function will extract the key purpose OIDs of the Certificate + * specified by the given index. These are stored in the Extended Key + * Usage extension (2.5.29.37) See the GNUTLS_KP_* definitions for + * human readable names. + * + * If @oid is null then only the size will be filled. + * + * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is + * not long enough, and in that case the *sizeof_oid will be updated + * with the required size. On success 0 is returned. + **/ +int +gnutls_x509_crq_get_key_purpose_oid (gnutls_x509_crq_t cert, + int indx, void *oid, size_t * sizeof_oid, + unsigned int *critical) +{ + char tmpstr[MAX_NAME_SIZE]; + int result, len; + gnutls_datum_t prev_data; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + opaque tmp[MAX_CRQ_EXTENSIONS_SIZE]; + size_t tmp_size; + + if (cert == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + if (oid) + memset (oid, 0, *sizeof_oid); + else + *sizeof_oid = 0; + + tmp_size = sizeof(tmp); + result = gnutls_x509_crq_get_extension_by_oid (cert, "2.5.29.37", 0, + tmp, &tmp_size, critical); + + if (result < 0 && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + { + gnutls_assert(); + return result; + } + + if (result < 0) + { + prev_data.data = NULL; + prev_data.size = 0; + } + else + { + prev_data.data = tmp; + prev_data.size = tmp_size; + } + + result = asn1_create_element + (_gnutls_get_pkix (), "PKIX1.ExtKeyUsageSyntax", &c2); + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + return _gnutls_asn2err (result); + } + + + if ( prev_data.size > 0) + { + result = asn1_der_decoding (&c2, prev_data.data, prev_data.size, NULL); + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + asn1_delete_structure (&c2); + return _gnutls_asn2err (result); + } + } + + indx++; + /* create a string like "?1" + */ + snprintf (tmpstr, sizeof (tmpstr), "?%u", indx); + + len = *sizeof_oid; + result = asn1_read_value (c2, tmpstr, oid, &len); + + *sizeof_oid = len; + asn1_delete_structure (&c2); + + if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) + { + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + if (result != ASN1_SUCCESS) + { + if (result != ASN1_MEM_ERROR) + gnutls_assert (); + return _gnutls_asn2err (result); + } + + return 0; + +} + +/** + * gnutls_x509_crq_set_key_purpose_oid - Sets the Certificate's key purpose OIDs + * @cert: a certificate of type #gnutls_x509_crq_t + * @oid: a pointer to a null terminated string that holds the OID + * @critical: Whether this extension will be critical or not + * + * This function will set the key purpose OIDs of the Certificate. + * These are stored in the Extended Key Usage extension (2.5.29.37) + * See the GNUTLS_KP_* definitions for human readable names. + * + * Subsequent calls to this function will append OIDs to the OID list. + * + * On success 0 is returned. + **/ +int +gnutls_x509_crq_set_key_purpose_oid (gnutls_x509_crq_t cert, + const void *oid, unsigned int critical) +{ + int result; + gnutls_datum_t prev_data, der_data; + ASN1_TYPE c2 = ASN1_TYPE_EMPTY; + opaque tmp[MAX_CRQ_EXTENSIONS_SIZE]; + size_t tmp_size; + + if (cert == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + /* Check if the extension already exists. + */ + tmp_size = sizeof(tmp); + result = gnutls_x509_crq_get_extension_by_oid (cert, "2.5.29.37", 0, + tmp, &tmp_size, NULL); + + if (result < 0 && result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + { + gnutls_assert(); + return result; + } + + if (result < 0) + { + prev_data.data = NULL; + prev_data.size = 0; + } + else + { + prev_data.data = tmp; + prev_data.size = tmp_size; + } + + result = asn1_create_element + (_gnutls_get_pkix (), "PKIX1.ExtKeyUsageSyntax", &c2); + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + return _gnutls_asn2err (result); + } + + if (prev_data.size > 0) + { + /* decode it. + */ + result = asn1_der_decoding (&c2, prev_data.data, prev_data.size, NULL); + + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + asn1_delete_structure (&c2); + return _gnutls_asn2err (result); + } + + } + + /* generate the extension. + */ + /* 1. create a new element. + */ + result = asn1_write_value (c2, "", "NEW", 1); + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + asn1_delete_structure (&c2); + return _gnutls_asn2err (result); + } + + /* 2. Add the OID. + */ + result = asn1_write_value (c2, "?LAST", oid, 1); + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + asn1_delete_structure (&c2); + return _gnutls_asn2err (result); + } + + result = _gnutls_x509_der_encode (c2, "", &der_data, 0); + asn1_delete_structure (&c2); + + if (result != ASN1_SUCCESS) + { + gnutls_assert (); + return _gnutls_asn2err (result); + } + + result = _gnutls_x509_crq_set_extension (cert, "2.5.29.37", + &der_data, critical); + + _gnutls_free_datum (&der_data); + + + if (result < 0) + { + gnutls_assert (); + return result; + } +} + #endif /* ENABLE_PKI */ diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c index 81ba84bef3..51b97abedd 100644 --- a/lib/x509/extensions.c +++ b/lib/x509/extensions.c @@ -582,8 +582,6 @@ _gnutls_x509_crq_set_extension (gnutls_x509_crq_t crq, result = gnutls_x509_crq_set_attribute_by_oid (crq, "1.2.840.113549.1.9.14", der.data, der.size); - - _gnutls_free_datum( &der); if (result < 0) { diff --git a/lib/x509/output.c b/lib/x509/output.c index 4451421484..69eb7ef50b 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -372,7 +372,7 @@ print_crldist (gnutls_string * str, gnutls_x509_crt_t cert) } static void -print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert) +print_key_purpose (gnutls_string * str, const char* prefix, int type, void* cert) { int indx; char *buffer = NULL; @@ -382,8 +382,13 @@ print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert) for (indx = 0;; indx++) { size = 0; - err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer, + if (type == TYPE_CRT) + err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer, + &size, NULL); + else + err = gnutls_x509_crq_get_key_purpose_oid (cert, indx, buffer, &size, NULL); + if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) return; if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) @@ -400,8 +405,13 @@ print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert) return; } - err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer, + if (type == TYPE_CRT) + err = gnutls_x509_crt_get_key_purpose_oid (cert, indx, buffer, + &size, NULL); + else + err = gnutls_x509_crq_get_key_purpose_oid (cert, indx, buffer, &size, NULL); + if (err < 0) { gnutls_free (buffer); @@ -411,21 +421,21 @@ print_key_purpose (gnutls_string * str, gnutls_x509_crt_t cert) } if (strcmp (buffer, GNUTLS_KP_TLS_WWW_SERVER) == 0) - addf (str, _("\t\t\tTLS WWW Server.\n")); + addf (str, _("%s\t\t\tTLS WWW Server.\n"), prefix); else if (strcmp (buffer, GNUTLS_KP_TLS_WWW_CLIENT) == 0) - addf (str, _("\t\t\tTLS WWW Client.\n")); + addf (str, _("%s\t\t\tTLS WWW Client.\n"), prefix); else if (strcmp (buffer, GNUTLS_KP_CODE_SIGNING) == 0) - addf (str, _("\t\t\tCode signing.\n")); + addf (str, _("%s\t\t\tCode signing.\n"), prefix); else if (strcmp (buffer, GNUTLS_KP_EMAIL_PROTECTION) == 0) - addf (str, _("\t\t\tEmail protection.\n")); + addf (str, _("%s\t\t\tEmail protection.\n"), prefix); else if (strcmp (buffer, GNUTLS_KP_TIME_STAMPING) == 0) - addf (str, _("\t\t\tTime stamping.\n")); + addf (str, _("%s\t\t\tTime stamping.\n"), prefix); else if (strcmp (buffer, GNUTLS_KP_OCSP_SIGNING) == 0) - addf (str, _("\t\t\tOCSP signing.\n")); + addf (str, _("%s\t\t\tOCSP signing.\n"), prefix); else if (strcmp (buffer, GNUTLS_KP_ANY) == 0) - addf (str, _("\t\t\tAny purpose.\n")); + addf (str, _("%s\t\t\tAny purpose.\n"), prefix); else - addf (str, "\t\t\t%s\n", buffer); + addf (str, "%s\t\t\t%s\n", prefix, buffer); gnutls_free (buffer); } @@ -718,7 +728,7 @@ int i, err; critical ? _("critical") : _("not critical")); #ifdef ENABLE_PKI - if (type == TYPE_CRT) print_key_purpose (str, cert); + print_key_purpose (str, prefix, type, cert); #endif keypurpose_idx++; diff --git a/src/certtool.c b/src/certtool.c index ba7a87dd29..7ff0fec800 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -1900,6 +1900,43 @@ generate_request (void) ret = get_crl_sign_status (); if (ret) usage |= GNUTLS_KEY_CRL_SIGN; + + ret = get_code_sign_status (); + if (ret) + { + ret = + gnutls_x509_crq_set_key_purpose_oid (crq, + GNUTLS_KP_CODE_SIGNING, + 0); + if (ret < 0) + error (EXIT_FAILURE, 0, "key_kp: %s", + gnutls_strerror (ret)); + } + + ret = get_ocsp_sign_status (); + if (ret) + { + ret = + gnutls_x509_crq_set_key_purpose_oid (crq, + GNUTLS_KP_OCSP_SIGNING, + 0); + if (ret < 0) + error (EXIT_FAILURE, 0, "key_kp: %s", + gnutls_strerror (ret)); + } + + ret = get_time_stamp_status (); + if (ret) + { + ret = + gnutls_x509_crq_set_key_purpose_oid (crq, + GNUTLS_KP_TIME_STAMPING, + 0); + if (ret < 0) + error (EXIT_FAILURE, 0, "key_kp: %s", + gnutls_strerror (ret)); + } + } ret = gnutls_x509_crq_set_key_usage (crq, usage); @@ -1907,6 +1944,24 @@ generate_request (void) error (EXIT_FAILURE, 0, "key_usage: %s", gnutls_strerror (ret)); + ret = get_tls_client_status (); + if (ret != 0) + { + ret = gnutls_x509_crq_set_key_purpose_oid (crq, + GNUTLS_KP_TLS_WWW_CLIENT, 0); + if (ret < 0) + error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret)); + } + + ret = get_tls_server_status (); + if (ret != 0) + { + ret = gnutls_x509_crq_set_key_purpose_oid (crq, + GNUTLS_KP_TLS_WWW_SERVER, 0); + if (ret < 0) + error (EXIT_FAILURE, 0, "key_kp: %s", gnutls_strerror (ret)); + } + ret = gnutls_x509_crq_set_key (crq, key); if (ret < 0) error (EXIT_FAILURE, 0, "set_key: %s", gnutls_strerror (ret)); @@ -1915,12 +1970,7 @@ generate_request (void) if (ret < 0) error (EXIT_FAILURE, 0, "sign: %s", gnutls_strerror (ret)); - size = sizeof (buffer); - ret = gnutls_x509_crq_export (crq, info.outcert_format, buffer, &size); - if (ret < 0) - error (EXIT_FAILURE, 0, "export: %s", gnutls_strerror (ret)); - - fwrite (buffer, 1, size, outfile); + print_crq_info (crq, outfile); gnutls_x509_crq_deinit (crq); gnutls_x509_privkey_deinit (key);