diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-03-30 08:31:24 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-03-30 08:31:24 +0000 |
commit | 1c088a8b6237ec67f63c23f97a0f2dc4e99af869 (patch) | |
tree | 7fff7c8329d19bbaa910312e746a116f28fbfaf5 /src/libstrongswan/crypto | |
parent | bcc8f7ca7fd8e8ff6e8a4d579251458313133598 (diff) | |
download | vyos-strongswan-1c088a8b6237ec67f63c23f97a0f2dc4e99af869.tar.gz vyos-strongswan-1c088a8b6237ec67f63c23f97a0f2dc4e99af869.zip |
[svn-upgrade] Integrating new upstream version, strongswan (4.1.11)
Diffstat (limited to 'src/libstrongswan/crypto')
-rw-r--r-- | src/libstrongswan/crypto/hashers/hasher.c | 38 | ||||
-rw-r--r-- | src/libstrongswan/crypto/hashers/hasher.h | 21 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ocsp.c | 8 | ||||
-rw-r--r-- | src/libstrongswan/crypto/ocsp.h | 5 | ||||
-rw-r--r-- | src/libstrongswan/crypto/pkcs7.c | 449 | ||||
-rw-r--r-- | src/libstrongswan/crypto/pkcs7.h | 85 | ||||
-rw-r--r-- | src/libstrongswan/crypto/pkcs9.c | 470 | ||||
-rw-r--r-- | src/libstrongswan/crypto/pkcs9.h | 121 | ||||
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_private_key.c | 123 | ||||
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_private_key.h | 6 | ||||
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_public_key.c | 117 | ||||
-rw-r--r-- | src/libstrongswan/crypto/rsa/rsa_public_key.h | 40 | ||||
-rwxr-xr-x | src/libstrongswan/crypto/x509.c | 94 | ||||
-rwxr-xr-x | src/libstrongswan/crypto/x509.h | 10 |
14 files changed, 1392 insertions, 195 deletions
diff --git a/src/libstrongswan/crypto/hashers/hasher.c b/src/libstrongswan/crypto/hashers/hasher.c index 14bfb022f..9fa778aa6 100644 --- a/src/libstrongswan/crypto/hashers/hasher.c +++ b/src/libstrongswan/crypto/hashers/hasher.c @@ -6,8 +6,9 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +21,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: hasher.c 3304 2007-10-12 23:18:42Z andreas $ + * RCSID $Id: hasher.c 3423 2008-01-22 10:32:37Z andreas $ */ @@ -110,6 +111,39 @@ hash_algorithm_t hasher_algorithm_from_oid(int oid) /* * Described in header. */ +int hasher_algorithm_to_oid(hash_algorithm_t alg) +{ + int oid; + + switch (alg) + { + case HASH_MD2: + oid = OID_MD2; + break; + case HASH_MD5: + oid = OID_MD5; + break; + case HASH_SHA1: + oid = OID_SHA1; + break; + case HASH_SHA256: + oid = OID_SHA256; + break; + case HASH_SHA384: + oid = OID_SHA384; + break; + case HASH_SHA512: + oid = OID_SHA512; + break; + default: + oid = OID_UNKNOWN; + } + return oid; +} + +/* + * Described in header. + */ int hasher_signature_algorithm_to_oid(hash_algorithm_t alg) { int oid; diff --git a/src/libstrongswan/crypto/hashers/hasher.h b/src/libstrongswan/crypto/hashers/hasher.h index 48b904576..e73de7f01 100644 --- a/src/libstrongswan/crypto/hashers/hasher.h +++ b/src/libstrongswan/crypto/hashers/hasher.h @@ -6,8 +6,9 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +21,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: hasher.h 3307 2007-10-17 02:56:24Z andreas $ + * RCSID $Id: hasher.h 3423 2008-01-22 10:32:37Z andreas $ */ #ifndef HASHER_H_ @@ -171,11 +172,23 @@ hasher_t *hasher_create(hash_algorithm_t hash_algorithm); hash_algorithm_t hasher_algorithm_from_oid(int oid); /** - * @brief Conversion of hash signature algorithm ASN.1 OID. + * @brief Conversion of hash algorithm into ASN.1 OID. + * + * @param alg hash algorithm + * @return + * - ASN.1 hash OID if known hash algorithm + * - OID_UNKNOW + * + * @ingroup hashers + */ +int hasher_algorithm_to_oid(hash_algorithm_t alg); + +/** + * @brief Conversion of hash signature algorithm into ASN.1 OID. * * @param alg hash algorithm * @return - * - ASN.1 OID if known hash algorithm + * - ASN.1 signature OID if known hash algorithm * - OID_UNKNOW * * @ingroup hashers diff --git a/src/libstrongswan/crypto/ocsp.c b/src/libstrongswan/crypto/ocsp.c index e4d907188..4bbec31de 100644 --- a/src/libstrongswan/crypto/ocsp.c +++ b/src/libstrongswan/crypto/ocsp.c @@ -6,8 +6,11 @@ */ /* Support of the Online Certificate Status Protocol (OCSP) + * * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen - * Zuercher Hochschule Winterthur + * Copyright (C) 2007 Andreas Steffen + * + * Hochschule für Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,6 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * + * RCSID $Id$ */ #include <unistd.h> @@ -325,7 +329,7 @@ static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo) chunk_t serialNumber = certinfo->get_serialNumber(certinfo); chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm", - ASN1_sha1_id, + asn1_algorithmIdentifier(OID_SHA1), asn1_simple_object(ASN1_OCTET_STRING, this->authNameID), asn1_simple_object(ASN1_OCTET_STRING, this->authKeyID), asn1_simple_object(ASN1_INTEGER, serialNumber)); diff --git a/src/libstrongswan/crypto/ocsp.h b/src/libstrongswan/crypto/ocsp.h index 42059e1c6..e468bb8be 100644 --- a/src/libstrongswan/crypto/ocsp.h +++ b/src/libstrongswan/crypto/ocsp.h @@ -6,9 +6,11 @@ */ /* Support of the Online Certificate Status Protocol (OCSP) Support + * * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen * Copyright (C) 2007 Andreas Steffen - * Hochschule fuer Technik Rapperswil, Switzerland + * + * Hochschule fuer Technik Rapperswil, Switzerland * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -20,6 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * + * RCSID $Id$ */ #ifndef OCSP_H_ diff --git a/src/libstrongswan/crypto/pkcs7.c b/src/libstrongswan/crypto/pkcs7.c index 70510471a..48d3e2d78 100644 --- a/src/libstrongswan/crypto/pkcs7.c +++ b/src/libstrongswan/crypto/pkcs7.c @@ -7,7 +7,8 @@ /* * Copyright (C) 2005 Jan Hutter, Martin Willi - * Copyright (C) 2002-2005 Andreas Steffen + * Copyright (C) 2002-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil, Switzerland * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +21,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: pkcs7.c 3302 2007-10-12 21:57:20Z andreas $ + * RCSID $Id: pkcs7.c 3438 2008-02-02 00:29:03Z andreas $ */ #include <stdlib.h> @@ -32,8 +33,11 @@ #include <asn1/asn1.h> #include <asn1/oid.h> #include <crypto/x509.h> +#include <crypto/pkcs9.h> #include <crypto/hashers/hasher.h> #include <crypto/crypters/crypter.h> +#include <crypto/rsa/rsa_public_key.h> +#include <utils/randomizer.h> #include <utils/linked_list.h> #include "pkcs7.h" @@ -77,7 +81,7 @@ struct private_pkcs7_t { /** * ASN.1 encoded attributes */ - chunk_t attributes; + pkcs9_t *attributes; /** * Linked list of X.509 certificates @@ -244,25 +248,7 @@ static const chunk_t ASN1_des_cbc_oid = chunk_from_buf(ASN1_des_cbc_oid_str); /** - * PKCS#7 attribute type OIDs - */ -static u_char ASN1_contentType_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03 -}; - -static u_char ASN1_messageDigest_oid_str[] = { - 0x06, 0x09, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04 -}; - -static const chunk_t ASN1_contentType_oid = - chunk_from_buf(ASN1_contentType_oid_str); -static const chunk_t ASN1_messageDigest_oid = - chunk_from_buf(ASN1_messageDigest_oid_str); - -/** - * Implements pkcs7_t.is_signedData. + * Implements pkcs7_t.is_data. */ static bool is_data(private_pkcs7_t *this) { @@ -278,7 +264,7 @@ static bool is_signedData(private_pkcs7_t *this) } /** - * Implements pkcs7_t.is_signedData. + * Implements pkcs7_t.is_envelopedData. */ static bool is_envelopedData(private_pkcs7_t *this) { @@ -316,6 +302,11 @@ static bool parse_data(private_pkcs7_t *this) { return FALSE; } + if (data.len == 0) + { + this->data = chunk_empty; + return TRUE; + } if (parse_asn1_simple_object(&data, ASN1_OCTET_STRING, this->level, "data")) { this->data = chunk_clone(data); @@ -328,7 +319,7 @@ static bool parse_data(private_pkcs7_t *this) } /** - * Parse PKCS#7 signedData content + * Implements pkcs7_t.parse_signedData. */ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) { @@ -363,11 +354,27 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) digest_alg = parse_algorithmIdentifier(object, level, NULL); break; case PKCS7_SIGNED_CONTENT_INFO: - this->data = chunk_clone(object); + { + chunk_t pureData; + pkcs7_t *data = pkcs7_create_from_chunk(object, level+1); + + if (data == NULL) + { + return FALSE; + } + if (!data->parse_data(data)) + { + data->destroy(data); + return FALSE; + } + pureData = data->get_data(data); + this->data = (pureData.len)? chunk_clone(pureData) : chunk_empty; + data->destroy(data); + } break; case PKCS7_SIGNED_CERT: { - x509_t *cert = x509_create_from_chunk(object, level+1); + x509_t *cert = x509_create_from_chunk(chunk_clone(object), level+1); if (cert) { @@ -389,8 +396,9 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) } break; case PKCS7_AUTH_ATTRIBUTES: - this->attributes = object; - *this->attributes.ptr = ASN1_SET; + *object.ptr = ASN1_SET; + this->attributes = pkcs9_create_from_chunk(object, level+1); + *object.ptr = ASN1_CONTEXT_C_0; break; case PKCS7_DIGEST_ALGORITHM: digest_alg = parse_algorithmIdentifier(object, level, NULL); @@ -407,8 +415,8 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) /* check the signature only if a cacert is available */ if (cacert != NULL) { - rsa_public_key_t *signer = cacert->get_public_key(cacert); hash_algorithm_t algorithm = hasher_algorithm_from_oid(digest_alg); + rsa_public_key_t *signer = cacert->get_public_key(cacert); if (signerInfos == 0) { @@ -420,7 +428,7 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) DBG1("more than one signerInfo object found"); return FALSE; } - if (this->attributes.ptr == NULL) + if (this->attributes == NULL) { DBG1("no authenticatedAttributes object found"); return FALSE; @@ -431,7 +439,7 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) return FALSE; } if (signer->verify_emsa_pkcs1_signature(signer, algorithm, - this->attributes, encrypted_digest) != SUCCESS) + this->attributes->get_encoding(this->attributes), encrypted_digest) != SUCCESS) { DBG1("invalid digest signature"); return FALSE; @@ -440,6 +448,39 @@ static bool parse_signedData(private_pkcs7_t *this, x509_t *cacert) { DBG2("digest signature is valid"); } + if (this->data.ptr != NULL) + { + chunk_t messageDigest = this->attributes->get_messageDigest(this->attributes); + + if (messageDigest.ptr == NULL) + { + DBG1("messageDigest attribute not found"); + return FALSE; + } + else + { + hasher_t *hasher = hasher_create(algorithm); + chunk_t hash; + bool valid; + + hasher->allocate_hash(hasher, this->data, &hash); + hasher->destroy(hasher); + DBG3("hash: %B", &hash); + + valid = chunk_equals(messageDigest, hash); + free(messageDigest.ptr); + free(hash.ptr); + if (valid) + { + DBG2("messageDigest is valid"); + } + else + { + DBG1("invalid messageDigest"); + return FALSE; + } + } + } } return TRUE; } @@ -574,8 +615,9 @@ static bool parse_envelopedData(private_pkcs7_t *this, chunk_t serialNumber, } /* decrypt the content */ + crypter->set_key(crypter, symmetric_key); crypter->decrypt(crypter, encrypted_content, iv, &this->data); - DBG4("decrypted content with padding: %B", &this->data); + DBG3("decrypted content with padding: %B", &this->data); /* remove the padding */ { @@ -611,7 +653,7 @@ failed: } /** - * Implements pkcs7_t.get_data + * Implements pkcs7_t.get_data. */ static chunk_t get_data(private_pkcs7_t *this) { @@ -619,7 +661,49 @@ static chunk_t get_data(private_pkcs7_t *this) } /** - * Implements pkcs_t.create_crluri_iterator + * Implements pkcs7_t.get_contentInfo. + */ +static chunk_t get_contentInfo(private_pkcs7_t *this) +{ + chunk_t content_type; + + /* select DER-encoded OID for pkcs7_contentInfo type */ + switch(this->type) + { + case OID_PKCS7_DATA: + content_type = ASN1_pkcs7_data_oid; + break; + case OID_PKCS7_SIGNED_DATA: + content_type = ASN1_pkcs7_signed_data_oid; + break; + case OID_PKCS7_ENVELOPED_DATA: + content_type = ASN1_pkcs7_enveloped_data_oid; + break; + case OID_PKCS7_SIGNED_ENVELOPED_DATA: + content_type = ASN1_pkcs7_signed_enveloped_data_oid; + break; + case OID_PKCS7_DIGESTED_DATA: + content_type = ASN1_pkcs7_digested_data_oid; + break; + case OID_PKCS7_ENCRYPTED_DATA: + content_type = ASN1_pkcs7_encrypted_data_oid; + break; + case OID_UNKNOWN: + default: + DBG1("invalid pkcs7 contentInfo type"); + return chunk_empty; + } + + return (this->content.ptr == NULL) + ? asn1_simple_object(ASN1_SEQUENCE, content_type) + : asn1_wrap(ASN1_SEQUENCE, "cm", + content_type, + asn1_simple_object(ASN1_CONTEXT_C_0, this->content) + ); +} + +/** + * Implements pkcs7_t.create_certificate_iterator */ static iterator_t *create_certificate_iterator(const private_pkcs7_t *this) { @@ -627,11 +711,243 @@ static iterator_t *create_certificate_iterator(const private_pkcs7_t *this) } /** + * Implements pkcs7_t.set_certificate + */ +static void set_certificate(private_pkcs7_t *this, x509_t *cert) +{ + if (cert) + { + /* TODO the certificate is currently not cloned */ + this->certs->insert_last(this->certs, cert); + } +} + +/** + * Implements pkcs7_t.set_attributes + */ +static void set_attributes(private_pkcs7_t *this, pkcs9_t *attributes) +{ + this->attributes = attributes; +} + +/** + * build a DER-encoded issuerAndSerialNumber object + */ +chunk_t pkcs7_build_issuerAndSerialNumber(x509_t *cert) +{ + identification_t *issuer = cert->get_issuer(cert); + + return asn1_wrap(ASN1_SEQUENCE, "cm", + issuer->get_encoding(issuer), + asn1_simple_object(ASN1_INTEGER, cert->get_serialNumber(cert))); +} + +/** + * Implements pkcs7_t.build_envelopedData. + */ +bool build_envelopedData(private_pkcs7_t *this, x509_t *cert, + encryption_algorithm_t alg) +{ + chunk_t iv, symmetricKey, in, out, alg_oid; + crypter_t *crypter; + + /* select OID of symmetric encryption algorithm */ + switch (alg) + { + case ENCR_DES: + alg_oid = ASN1_des_cbc_oid; + break; + case ENCR_3DES: + alg_oid = ASN1_3des_ede_cbc_oid; + break; + default: + DBG1(" encryption algorithm %N not supported", + encryption_algorithm_names, alg); + return FALSE; + } + + crypter = crypter_create(alg, 0); + if (crypter == NULL) + { + DBG1(" could not create crypter for algorithm %N", + encryption_algorithm_names, alg); + return FALSE; + } + + /* generate a true random symmetric encryption key + * and a pseudo-random iv + */ + { + randomizer_t *randomizer = randomizer_create(); + + randomizer->allocate_random_bytes(randomizer, + crypter->get_key_size(crypter), &symmetricKey); + DBG4(" symmetric encryption key: %B", &symmetricKey); + + randomizer->allocate_pseudo_random_bytes(randomizer, + crypter->get_block_size(crypter), &iv); + DBG4(" initialization vector: %B", &iv); + + randomizer->destroy(randomizer); + } + + /* pad the data so that the total length becomes + * a multiple of the block size + */ + { + size_t block_size = crypter->get_block_size(crypter); + size_t padding = block_size - this->data.len % block_size; + + in.len = this->data.len + padding; + in.ptr = malloc(in.len); + + DBG2(" padding %d bytes of data to multiple block size of %d bytes", + (int)this->data.len, (int)in.len); + + /* copy data */ + memcpy(in.ptr, this->data.ptr, this->data.len); + /* append padding */ + memset(in.ptr + this->data.len, padding, padding); + } + DBG3(" padded unencrypted data: %B", &in); + + /* symmetric encryption of data object */ + crypter->set_key(crypter, symmetricKey); + crypter->encrypt(crypter, in, iv, &out); + crypter->destroy(crypter); + chunk_free_randomized(&in); + DBG3(" encrypted data: %B", &out); + + /* build pkcs7 enveloped data object */ + { + chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm", + alg_oid, + asn1_wrap(ASN1_OCTET_STRING, "m", iv)); + + chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm", + ASN1_pkcs7_data_oid, + contentEncryptionAlgorithm, + asn1_wrap(ASN1_CONTEXT_S_0, "m", out)); + + chunk_t wrappedKey, encryptedKey, recipientInfo; + + rsa_public_key_t *public_key = cert->get_public_key(cert); + + public_key->pkcs1_encrypt(public_key, symmetricKey, &wrappedKey); + chunk_free_randomized(&symmetricKey); + + encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", wrappedKey); + + recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm", + ASN1_INTEGER_0, + pkcs7_build_issuerAndSerialNumber(cert), + asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), + encryptedKey); + + this->content = asn1_wrap(ASN1_SEQUENCE, "cmm", + ASN1_INTEGER_0, + asn1_wrap(ASN1_SET, "m", recipientInfo), + encryptedContentInfo); + this->type = OID_PKCS7_ENVELOPED_DATA; + } + return TRUE; +} + +/** + * Implements pkcs7_t.build_signedData. + */ +bool build_signedData(private_pkcs7_t *this, rsa_private_key_t *private_key, + hash_algorithm_t alg) +{ + int signature_oid = hasher_signature_algorithm_to_oid(alg); + chunk_t authenticatedAttributes = chunk_empty; + chunk_t encryptedDigest = chunk_empty; + chunk_t signerInfo; + x509_t *cert; + + if (this->certs->get_first(this->certs, (void**)&cert) != SUCCESS) + { + DBG1(" no pkcs7 signer certificate found"); + return FALSE; + } + + if (this->attributes != NULL) + { + if (this->data.ptr != NULL) + { + /* take the current time as signingTime */ + time_t now = time(NULL); + chunk_t signingTime = timetoasn1(&now, ASN1_UTCTIME); + + chunk_t messageDigest, attributes; + hasher_t *hasher = hasher_create(alg); + + hasher->allocate_hash(hasher, this->data, &messageDigest); + hasher->destroy(hasher); + this->attributes->set_attribute(this->attributes, + OID_PKCS9_CONTENT_TYPE, ASN1_pkcs7_data_oid); + this->attributes->set_messageDigest(this->attributes, + messageDigest); + this->attributes->set_attribute(this->attributes, + OID_PKCS9_SIGNING_TIME, signingTime); + attributes = this->attributes->get_encoding(this->attributes); + + free(messageDigest.ptr); + free(signingTime.ptr); + + private_key->build_emsa_pkcs1_signature(private_key, alg, + attributes, &encryptedDigest); + authenticatedAttributes = chunk_clone(attributes); + *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0; + } + } + else if (this->data.ptr != NULL) + { + private_key->build_emsa_pkcs1_signature(private_key, alg, + this->data, &encryptedDigest); + } + if (encryptedDigest.ptr) + { + encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest); + } + + signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmcm", + ASN1_INTEGER_1, + pkcs7_build_issuerAndSerialNumber(cert), + asn1_algorithmIdentifier(signature_oid), + authenticatedAttributes, + asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), + encryptedDigest); + + if (this->data.ptr != NULL) + { + this->content = asn1_simple_object(ASN1_OCTET_STRING, this->data); + chunk_free(&this->data); + } + this->type = OID_PKCS7_DATA; + this->data = get_contentInfo(this); + chunk_free(&this->content); + + this->type = OID_PKCS7_SIGNED_DATA; + + this->content = asn1_wrap(ASN1_SEQUENCE, "cmcmm", + ASN1_INTEGER_1, + asn1_simple_object(ASN1_SET, asn1_algorithmIdentifier(signature_oid)), + this->data, + asn1_simple_object(ASN1_CONTEXT_C_0, cert->get_certificate(cert)), + asn1_wrap(ASN1_SET, "m", signerInfo)); + + return TRUE; +} + +/** * Implements pkcs7_t.destroy */ static void destroy(private_pkcs7_t *this) { + DESTROY_IF(this->attributes); this->certs->destroy_offset(this->certs, offsetof(x509_t, destroy)); + free(this->content.ptr); free(this->data.ptr); free(this); } @@ -665,19 +981,19 @@ static bool parse_contentInfo(chunk_t blob, u_int level0, private_pkcs7_t *cInfo return FALSE; } } - else if (objectID == PKCS7_INFO_CONTENT) + else if (objectID == PKCS7_INFO_CONTENT && object.len > 0) { - cInfo->content = object; + cInfo->content = chunk_clone(object); } objectID++; } return TRUE; } -/* - * Described in header. +/** + * Generic private constructor */ -pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level) +static private_pkcs7_t *pkcs7_create_empty(void) { private_pkcs7_t *this = malloc_thing(private_pkcs7_t); @@ -685,9 +1001,9 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level) this->type = OID_UNKNOWN; this->content = chunk_empty; this->parsed = FALSE; - this->level = level + 2; + this->level = 0; this->data = chunk_empty; - this->attributes = chunk_empty; + this->attributes = NULL; this->certs = linked_list_create(); /*public functions */ @@ -698,9 +1014,25 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level) this->public.parse_signedData = (bool (*) (pkcs7_t*,x509_t*))parse_signedData; this->public.parse_envelopedData = (bool (*) (pkcs7_t*,chunk_t,rsa_private_key_t*))parse_envelopedData; this->public.get_data = (chunk_t (*) (pkcs7_t*))get_data; + this->public.get_contentInfo = (chunk_t (*) (pkcs7_t*))get_contentInfo; this->public.create_certificate_iterator = (iterator_t* (*) (pkcs7_t*))create_certificate_iterator; + this->public.set_certificate = (void (*) (pkcs7_t*,x509_t*))set_certificate; + this->public.set_attributes = (void (*) (pkcs7_t*,pkcs9_t*))set_attributes; + this->public.build_envelopedData = (bool (*) (pkcs7_t*,x509_t*,encryption_algorithm_t))build_envelopedData; + this->public.build_signedData = (bool (*) (pkcs7_t*,rsa_private_key_t*,hash_algorithm_t))build_signedData; this->public.destroy = (void (*) (pkcs7_t*))destroy; + return this; +} + +/* + * Described in header. + */ +pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level) +{ + private_pkcs7_t *this = pkcs7_create_empty(); + + this->level = level + 2; if (!parse_contentInfo(chunk, level, this)) { destroy(this); @@ -708,3 +1040,38 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level) } return &this->public; } + +/* + * Described in header. + */ +pkcs7_t *pkcs7_create_from_data(chunk_t data) +{ + private_pkcs7_t *this = pkcs7_create_empty(); + + this->data = chunk_clone(data); + this->parsed = TRUE; + + return &this->public; +} + +/* + * Described in header. + */ +pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label) +{ + bool pgp = FALSE; + chunk_t chunk = chunk_empty; + char cert_label[BUF_LEN]; + pkcs7_t *pkcs7; + + snprintf(cert_label, BUF_LEN, "%s pkcs7", label); + + if (!pem_asn1_load_file(filename, NULL, cert_label, &chunk, &pgp)) + { + return NULL; + } + + pkcs7 = pkcs7_create_from_chunk(chunk, 0); + free(chunk.ptr); + return pkcs7; +} diff --git a/src/libstrongswan/crypto/pkcs7.h b/src/libstrongswan/crypto/pkcs7.h index c8434225a..74bd25361 100644 --- a/src/libstrongswan/crypto/pkcs7.h +++ b/src/libstrongswan/crypto/pkcs7.h @@ -7,7 +7,7 @@ /* * Copyright (C) 2005 Jan Hutter, Martin Willi - * Copyright (C) 2002-2007 Andreas Steffen + * Copyright (C) 2002-2008 Andreas Steffen * * Hochschule fuer Technik Rapperswil, Switzerland * @@ -21,7 +21,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: pkcs7.h 3302 2007-10-12 21:57:20Z andreas $ + * RCSID $Id: pkcs7.h 3437 2008-02-01 22:26:01Z andreas $ */ #ifndef _PKCS7_H @@ -31,7 +31,9 @@ typedef struct pkcs7_t pkcs7_t; #include <library.h> #include <crypto/x509.h> +#include <crypto/pkcs9.h> #include <crypto/rsa/rsa_private_key.h> +#include <crypto/crypters/crypter.h> #include <utils/iterator.h> /** @@ -39,6 +41,7 @@ typedef struct pkcs7_t pkcs7_t; * * @b Constructors: * -pkcs7_create_from_chunk() + * -pkcs7_create_from_data() * * @ingroup crypto */ @@ -103,14 +106,66 @@ struct pkcs7_t { chunk_t (*get_data) (pkcs7_t *this); /** + * @brief Returns the a DER-encoded contentInfo object + * + * @param this calling object + * @return chunk containing the contentInfo object + */ + chunk_t (*get_contentInfo) (pkcs7_t *this); + + /** * @brief Create an iterator for the certificates. * - * @param this calling object - * @return iterator for the certificates + * @param this calling object + * @return iterator for the certificates */ iterator_t *(*create_certificate_iterator) (pkcs7_t *this); /** + * @brief Add a certificate. + * + * @param this calling object + * @param cert certificate to be included + */ + void (*set_certificate) (pkcs7_t *this, x509_t *cert); + + /** + * @brief Add authenticated attributes. + * + * @param this calling object + * @param attributes attributes to be included + */ + void (*set_attributes) (pkcs7_t *this, pkcs9_t *attributes); + + /** + * @brief Build a data object + * + * @param this PKCS#7 data to be built + * @return TRUE if build was successful + */ + bool (*build_data) (pkcs7_t *this); + + /** + * @brief Build an envelopedData object + * + * @param this PKCS#7 data object to envelop + * @param cert receivers's certificate + * @param alg encryption algorithm + * @return TRUE if build was successful + */ + bool (*build_envelopedData) (pkcs7_t *this, x509_t *cert, encryption_algorithm_t alg); + + /** + * @brief Build an signedData object + * + * @param this PKCS#7 data object to sign + * @param key signer's RSA private key + * @param alg digest algorithm used for signature + * @return TRUE if build was successful + */ + bool (*build_signedData) (pkcs7_t *this, rsa_private_key_t *key, hash_algorithm_t alg); + + /** * @brief Destroys the contentInfo object. * * @param this PKCS#7 contentInfo object to destroy @@ -129,4 +184,26 @@ struct pkcs7_t { */ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level); +/** + * @brief Create a PKCS#7 contentInfo object + * + * @param chunk chunk containing data + * @return created pkcs7_contentInfo object. + * + * @ingroup crypto + */ +pkcs7_t *pkcs7_create_from_data(chunk_t data); + +/** + * @brief Read a X.509 certificate from a DER encoded file. + * + * @param filename file containing DER encoded data + * @param label label describing kind of PKCS#7 file + * @return created pkcs7_t object, or NULL if invalid. + * + * @ingroup crypto + */ +pkcs7_t *pkcs7_create_from_file(const char *filename, const char *label); + + #endif /* _PKCS7_H */ diff --git a/src/libstrongswan/crypto/pkcs9.c b/src/libstrongswan/crypto/pkcs9.c new file mode 100644 index 000000000..1003c9011 --- /dev/null +++ b/src/libstrongswan/crypto/pkcs9.c @@ -0,0 +1,470 @@ +/** + * @file pkcs9.c + * + * @brief Implementation of pkcs9_t. + * + */ + +/* + * Copyright (C)2008 Andreas Steffen + * + * Hochschule fuer Technik Rapperswil, Switzerland + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * RCSID $Id: pkcs7.c 3423 2008-01-22 10:32:37Z andreas $ + */ + +#include <library.h> +#include <debug.h> + +#include <asn1/oid.h> +#include <asn1/asn1.h> +#include <utils/linked_list.h> + +#include "pkcs9.h" + +typedef struct private_pkcs9_t private_pkcs9_t; + +/** + * Private data of a pkcs9_t attribute list. + */ +struct private_pkcs9_t { + /** + * Public interface + */ + pkcs9_t public; + + /** + * DER encoding of PKCS#9 attributes + */ + chunk_t encoding; + + /** + * Linked list of PKCS#9 attributes + */ + linked_list_t *attributes; +}; + +typedef struct attribute_t attribute_t; + +/** + * Definition of an attribute_t object. + */ +struct attribute_t { + /** + * Object Identifier (OID) + */ + int oid; + + /** + * Attribute value + */ + chunk_t value; + + /** + * ASN.1 encoding + */ + chunk_t encoding; + + /** + * Destroys the attribute. + * + * @param this attribute to destroy + */ + void (*destroy) (attribute_t *this); + +}; + +/* ASN.1 definition of the X.501 atttribute type */ + +static const asn1Object_t attributesObjects[] = { + { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */ + { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */ + { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */ + { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */ + { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */ + { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */ +}; + +#define ATTRIBUTE_OBJ_TYPE 2 +#define ATTRIBUTE_OBJ_VALUE 4 +#define ATTRIBUTE_OBJ_ROOF 7 + +/** + * PKCS#9 attribute type OIDs + */ +static u_char ASN1_contentType_oid_str[] = { + 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03 +}; + +static u_char ASN1_messageDigest_oid_str[] = { + 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04 +}; + +static u_char ASN1_signingTime_oid_str[] = { + 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x05 +}; + +static char ASN1_messageType_oid_str[] = { + 0x06, 0x0A, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x02 +}; + +static char ASN1_senderNonce_oid_str[] = { + 0x06, 0x0A, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x05 +}; + +static char ASN1_transId_oid_str[] = { + 0x06, 0x0A, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, 0x09, 0x07 +}; + +static const chunk_t ASN1_contentType_oid = + chunk_from_buf(ASN1_contentType_oid_str); +static const chunk_t ASN1_messageDigest_oid = + chunk_from_buf(ASN1_messageDigest_oid_str); +static const chunk_t ASN1_signingTime_oid = + chunk_from_buf(ASN1_signingTime_oid_str); +static const chunk_t ASN1_messageType_oid = + chunk_from_buf(ASN1_messageType_oid_str); +static const chunk_t ASN1_senderNonce_oid = + chunk_from_buf(ASN1_senderNonce_oid_str); +static const chunk_t ASN1_transId_oid = + chunk_from_buf(ASN1_transId_oid_str); + +/** + * return the ASN.1 encoded OID of a PKCS#9 attribute + */ +static chunk_t asn1_attributeIdentifier(int oid) +{ + switch (oid) + { + case OID_PKCS9_CONTENT_TYPE: + return ASN1_contentType_oid; + case OID_PKCS9_MESSAGE_DIGEST: + return ASN1_messageDigest_oid; + case OID_PKCS9_SIGNING_TIME: + return ASN1_signingTime_oid; + case OID_PKI_MESSAGE_TYPE: + return ASN1_messageType_oid; + case OID_PKI_SENDER_NONCE: + return ASN1_senderNonce_oid; + case OID_PKI_TRANS_ID: + return ASN1_transId_oid;; + default: + return chunk_empty; + } +} + +/** + * return the ASN.1 encoding of a PKCS#9 attribute + */ +static asn1_t asn1_attributeType(int oid) +{ + asn1_t type; + + switch (oid) + { + case OID_PKCS9_CONTENT_TYPE: + type = ASN1_OID; + break; + case OID_PKCS9_SIGNING_TIME: + type = ASN1_UTCTIME; + break; + case OID_PKCS9_MESSAGE_DIGEST: + type = ASN1_OCTET_STRING; + break; + case OID_PKI_MESSAGE_TYPE: + type = ASN1_PRINTABLESTRING; + break; + case OID_PKI_STATUS: + type = ASN1_PRINTABLESTRING; + break; + case OID_PKI_FAIL_INFO: + type = ASN1_PRINTABLESTRING; + break; + case OID_PKI_SENDER_NONCE: + type = ASN1_OCTET_STRING; + break; + case OID_PKI_RECIPIENT_NONCE: + type = ASN1_OCTET_STRING; + break; + case OID_PKI_TRANS_ID: + type = ASN1_PRINTABLESTRING; + break; + default: + type = ASN1_EOC; + } + return type; +} + +/** + * Destroy an attribute_t object. + */ +static void attribute_destroy(attribute_t *this) +{ + free(this->value.ptr); + free(this->encoding.ptr); + free(this); +} + +/** + * Create an attribute_t object. + */ +static attribute_t *attribute_create(int oid, chunk_t value) +{ + attribute_t *this = malloc_thing(attribute_t); + + this->oid = oid; + this->value = chunk_clone(value); + this->encoding = asn1_wrap(ASN1_SEQUENCE, "cm", + asn1_attributeIdentifier(oid), + asn1_simple_object(ASN1_SET, value)); + this->destroy = (void (*) (attribute_t*))attribute_destroy; + return this; +} + +/** + * Implements pkcs9_t.build_encoding + */ +static void build_encoding(private_pkcs9_t *this) +{ + iterator_t *iterator; + attribute_t *attribute; + u_int attributes_len = 0; + + if (this->encoding.ptr) + { + chunk_free(&this->encoding); + } + if (this->attributes->get_count(this->attributes) == 0) + { + return; + } + + /* compute the total length of the encoded attributes */ + iterator = this->attributes->create_iterator(this->attributes, TRUE); + + while (iterator->iterate(iterator, (void**)&attribute)) + { + attributes_len += attribute->encoding.len; + } + iterator->destroy(iterator); + + /* allocate memory for the attributes and build the encoding */ + { + u_char *pos = build_asn1_object(&this->encoding, ASN1_SET, attributes_len); + + iterator = this->attributes->create_iterator(this->attributes, TRUE); + + while (iterator->iterate(iterator, (void**)&attribute)) + { + memcpy(pos, attribute->encoding.ptr, attribute->encoding.len); + pos += attribute->encoding.len; + } + iterator->destroy(iterator); + } +} + +/** + * Implements pkcs9_t.get_encoding + */ +static chunk_t get_encoding(private_pkcs9_t *this) +{ + if (this->encoding.ptr == NULL) + { + build_encoding(this); + } + return this->encoding; +} + +/** + * Implements pkcs9_t.get_attribute + */ +static chunk_t get_attribute(private_pkcs9_t *this, int oid) +{ + iterator_t *iterator = this->attributes->create_iterator(this->attributes, TRUE); + chunk_t value = chunk_empty; + attribute_t *attribute; + + while (iterator->iterate(iterator, (void**)&attribute)) + { + if (attribute->oid == oid) + { + value = attribute->value; + break; + } + } + iterator->destroy(iterator); + return value; +} + +/** + * Implements pkcs9_t.set_attribute + */ +static void set_attribute(private_pkcs9_t *this, int oid, chunk_t value) +{ + attribute_t *attribute = attribute_create(oid, value); + + this->attributes->insert_last(this->attributes, (void*)attribute); +} + +/** + * Implements pkcs9_t.get_messageDigest + */ +static chunk_t get_messageDigest(private_pkcs9_t *this) +{ + const int oid = OID_PKCS9_MESSAGE_DIGEST; + chunk_t value = get_attribute(this, oid); + + if (value.ptr == NULL) + { + return chunk_empty; + } + if (!parse_asn1_simple_object(&value, asn1_attributeType(oid), 0, oid_names[oid].name)) + { + return chunk_empty; + } + return chunk_clone(value); +} + +/** + * Implements pkcs9_t.set_attribute + */ +static void set_messageDigest(private_pkcs9_t *this, chunk_t value) +{ + const int oid = OID_PKCS9_MESSAGE_DIGEST; + chunk_t messageDigest = asn1_simple_object(asn1_attributeType(oid), value); + + set_attribute(this, oid, messageDigest); + free(messageDigest.ptr); +} + +/** + * Implements pkcs9_t.destroy + */ +static void destroy(private_pkcs9_t *this) +{ + this->attributes->destroy_offset(this->attributes, offsetof(attribute_t, destroy)); + free(this->encoding.ptr); + free(this); +} + +/** + * Generic private constructor + */ +static private_pkcs9_t *pkcs9_create_empty(void) +{ + private_pkcs9_t *this = malloc_thing(private_pkcs9_t); + + /* initialize */ + this->encoding = chunk_empty; + this->attributes = linked_list_create(); + + /*public functions */ + this->public.build_encoding = (void (*) (pkcs9_t*))build_encoding; + this->public.get_encoding = (chunk_t (*) (pkcs9_t*))get_encoding; + this->public.get_attribute = (chunk_t (*) (pkcs9_t*,int))get_attribute; + this->public.set_attribute = (void (*) (pkcs9_t*,int,chunk_t))set_attribute; + this->public.get_messageDigest = (chunk_t (*) (pkcs9_t*))get_messageDigest; + this->public.set_messageDigest = (void (*) (pkcs9_t*,chunk_t))set_messageDigest; + this->public.destroy = (void (*) (pkcs9_t*))destroy; + + return this; +} + +/* + * Described in header. + */ +pkcs9_t *pkcs9_create(void) +{ + private_pkcs9_t *this = pkcs9_create_empty(); + + return &this->public; +} + +/** + * Parse a PKCS#9 attribute list + */ +static bool parse_attributes(chunk_t chunk, int level0, private_pkcs9_t* this) +{ + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int oid = OID_UNKNOWN; + int objectID = 0; + + asn1_init(&ctx, chunk, level0, FALSE, FALSE); + + while (objectID < ATTRIBUTE_OBJ_ROOF) + { + if (!extract_object(attributesObjects, &objectID, &object, &level, &ctx)) + { + return FALSE; + } + + switch (objectID) + { + case ATTRIBUTE_OBJ_TYPE: + oid = known_oid(object); + break; + case ATTRIBUTE_OBJ_VALUE: + if (oid == OID_UNKNOWN) + { + break; + } + /* add the attribute to a linked list */ + { + attribute_t *attribute = attribute_create(oid, object); + + this->attributes->insert_last(this->attributes, (void*)attribute); + } + /* parse known attributes */ + { + asn1_t type = asn1_attributeType(oid); + + if (type != ASN1_EOC) + { + if (!parse_asn1_simple_object(&object, type, level+1, oid_names[oid].name)) + { + return FALSE; + } + } + } + } + objectID++; + } + return TRUE; +} + + + /* + * Described in header. + */ +pkcs9_t *pkcs9_create_from_chunk(chunk_t chunk, u_int level) +{ + private_pkcs9_t *this = pkcs9_create_empty(); + + this->encoding = chunk_clone(chunk); + + if (!parse_attributes(chunk, level, this)) + { + destroy(this); + return NULL; + } + return &this->public; +} diff --git a/src/libstrongswan/crypto/pkcs9.h b/src/libstrongswan/crypto/pkcs9.h new file mode 100644 index 000000000..44915720c --- /dev/null +++ b/src/libstrongswan/crypto/pkcs9.h @@ -0,0 +1,121 @@ +/** + * @file pkcs7.h + * + * @brief Interface of pkcs9_t. + * + */ + +/* + * Copyright (C) 2008 Andreas Steffen + * + * Hochschule fuer Technik Rapperswil, Switzerland + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * RCSID $Id: pkcs7.h 3423 2008-01-22 10:32:37Z andreas $ + */ + +#ifndef _PKCS9_H +#define _PKCS9_H + +typedef struct pkcs9_t pkcs9_t; + +#include <library.h> + +/** + * @brief PKCS#9 . + * + * @b Constructors: + * -pkcs9_create_from_chunk() + * -pkcs9_create() + * + * @ingroup crypto + */ +struct pkcs9_t { + /** + * @brief generate ASN.1 encoding of attribute list + * + * @param this PKCS#9 attribute list to be encoded + */ + void (*build_encoding) (pkcs9_t *this); + + /** + * @brief gets ASN.1 encoding of PKCS#9 attribute list + * + * @param this calling object + * @return ASN.1 encoded PKCSI#9 list + */ + chunk_t (*get_encoding) (pkcs9_t *this); + + /** + * @brief gets a PKCS#9 attribute + * + * @param this calling object + * @param oid OID of the attribute + * @return ASN.1 encoded value of the attribute + */ + chunk_t (*get_attribute) (pkcs9_t *this, int oid); + + /** + * @brief adds a PKCS#9 attribute + * + * @param this calling object + * @param oid OID of the attribute + * @param value ASN.1 encoded value of the attribute + */ + void (*set_attribute) (pkcs9_t *this, int oid, chunk_t value); + + /** + * @brief gets a PKCS#9 messageDigest attribute + * + * @param this calling object + * @return messageDigest + */ + chunk_t (*get_messageDigest) (pkcs9_t *this); + + /** + * @brief add a PKCS#9 messageDigest attribute + * + * @param this calling object + * @param value messageDigest + */ + void (*set_messageDigest) (pkcs9_t *this, chunk_t value); + + /** + * @brief Destroys the PKCS#9 attribute list. + * + * @param this PKCS#9 attribute list to destroy + */ + void (*destroy) (pkcs9_t *this); +}; + +/** + * @brief Read a PKCS#9 attribute list from a DER encoded chunk. + * + * @param chunk chunk containing DER encoded data + * @param level ASN.1 parsing start level + * @return created pkcs9 attribute list, or NULL if invalid. + * + * @ingroup crypto + */ +pkcs9_t *pkcs9_create_from_chunk(chunk_t chunk, u_int level); + +/** + * @brief Create an empty PKCS#9 attribute list + * + * @param chunk chunk containing data + * @return created pkcs9 attribute list. + * + * @ingroup crypto + */ +pkcs9_t *pkcs9_create(void); + +#endif /* _PKCS9_H */ diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.c b/src/libstrongswan/crypto/rsa/rsa_private_key.c index ec2f2fc74..1b1499887 100644 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.c +++ b/src/libstrongswan/crypto/rsa/rsa_private_key.c @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_private_key.c 3306 2007-10-17 02:55:53Z andreas $ + * RCSID $Id: rsa_private_key.c 3429 2008-01-27 20:59:22Z andreas $ */ #include <gmp.h> @@ -40,6 +42,7 @@ * defined in rsa_public_key.c */ extern chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e); +extern chunk_t rsa_public_key_id_create(const mpz_t n, const mpz_t e); /** * Public exponent to use for key generation. @@ -111,7 +114,6 @@ struct private_rsa_private_key_t { * Keyid formed as a SHA-1 hash of a publicKeyInfo object */ chunk_t keyid; - /** * @brief Implements the RSADP algorithm specified in PKCS#1. @@ -129,16 +131,6 @@ struct private_rsa_private_key_t { * @return processed data */ chunk_t (*rsasp1) (private_rsa_private_key_t *this, chunk_t data); - - /** - * @brief Generate a prime value. - * - * @param this calling object - * @param prime_size size of the prime, in bytes - * @param[out] prime uninitialized mpz - */ - status_t (*compute_prime) (private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime); - }; /* ASN.1 definition of a PKCS#1 RSA private key */ @@ -173,8 +165,6 @@ static const asn1Object_t privkey_objects[] = { #define PRIV_KEY_COEFF 9 #define PRIV_KEY_ROOF 16 -static private_rsa_private_key_t *rsa_private_key_create_empty(void); - /** * Auxiliary function overwriting private key material with * pseudo-random bytes before releasing it @@ -196,9 +186,9 @@ static void mpz_clear_randomized(mpz_t z) } /** - * Implementation of private_rsa_private_key_t.compute_prime. + * Generate a random prime number with prime_len bytes */ -static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime) +static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_len, mpz_t *prime) { randomizer_t *randomizer; chunk_t random_bytes; @@ -209,7 +199,8 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size do { - status = randomizer->allocate_random_bytes(randomizer, prime_size, &random_bytes); + DBG1(" generating %d bit prime from %s ...", BITS_PER_BYTE * prime_len, DEV_RANDOM); + status = randomizer->allocate_random_bytes(randomizer, prime_len, &random_bytes); if (status != SUCCESS) { randomizer->destroy(randomizer); @@ -230,7 +221,7 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size chunk_free_randomized(&random_bytes); } /* check if it isnt too large */ - while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size); + while (((mpz_sizeinbase(*prime, 2) + 7) / BITS_PER_BYTE) > prime_len); randomizer->destroy(randomizer); return SUCCESS; @@ -269,7 +260,7 @@ static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data) } /** - * Implementation of rsa_private_key_t.eme_pkcs1_decrypt. + * Implementation of rsa_private_key_t.pkcs1_decrypt. */ static status_t pkcs1_decrypt(private_rsa_private_key_t *this, chunk_t in, chunk_t *out) @@ -319,47 +310,14 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, chunk_t data, chunk_t *signature) { hasher_t *hasher; - chunk_t em, digestInfo, hash_id, hash; - - /* get oid string prepended to hash */ - switch (hash_algorithm) - { - case HASH_MD2: - { - hash_id =ASN1_md2_id; - break; - } - case HASH_MD5: - { - hash_id = ASN1_md5_id; - break; - } - case HASH_SHA1: - { - hash_id = ASN1_sha1_id; - break; - } - case HASH_SHA256: - { - hash_id = ASN1_sha256_id; - break; - } - case HASH_SHA384: - { - hash_id = ASN1_sha384_id; - break; - } - case HASH_SHA512: - { - hash_id = ASN1_sha512_id; - break; - } - default: - { - return NOT_SUPPORTED; - } + chunk_t em, digestInfo, hash; + int hash_oid = hasher_algorithm_to_oid(hash_algorithm); + + if (hash_oid == OID_UNKNOWN) + { + return NOT_SUPPORTED; } - + /* get hasher */ hasher = hasher_create(hash_algorithm); if (hasher == NULL) @@ -373,7 +331,7 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, /* build DER-encoded digestInfo */ digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm", - hash_id, + asn1_algorithmIdentifier(hash_oid), asn1_simple_object(ASN1_OCTET_STRING, hash) ); chunk_free(&hash); @@ -432,7 +390,7 @@ static bool pkcs1_write(private_rsa_private_key_t *this, const char *filename, b */ rsa_public_key_t *get_public_key(private_rsa_private_key_t *this) { - return NULL; + return rsa_public_key_create(this->n, this->e); } /** @@ -455,13 +413,13 @@ static status_t check(private_rsa_private_key_t *this) /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets. * We actually require more (for security). */ - if (this->k < 512/8) + if (this->k < 512 / BITS_PER_BYTE) { return FAILED; } /* we picked a max modulus size to simplify buffer allocation */ - if (this->k > 8192/8) + if (this->k > 8192 / BITS_PER_BYTE) { return FAILED; } @@ -572,7 +530,6 @@ static private_rsa_private_key_t *rsa_private_key_create_empty(void) /* private functions */ this->rsadp = rsadp; this->rsasp1 = rsadp; /* same algorithm */ - this->compute_prime = compute_prime; this->keyid = chunk_empty; @@ -587,20 +544,17 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size) mpz_t p, q, n, e, d, exp1, exp2, coeff; mpz_t m, q1, t; private_rsa_private_key_t *this; - - this = rsa_private_key_create_empty(); - key_size = key_size / 8; + size_t key_len = key_size / BITS_PER_BYTE; + size_t prime_len = key_len / 2; /* Get values of primes p and q */ - if (this->compute_prime(this, key_size/2, &p) != SUCCESS) + if (compute_prime(this, prime_len, &p) != SUCCESS) { - free(this); return NULL; } - if (this->compute_prime(this, key_size/2, &q) != SUCCESS) + if (compute_prime(this, prime_len, &q) != SUCCESS) { mpz_clear(p); - free(this); return NULL; } @@ -648,7 +602,13 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size) mpz_clear_randomized(m); mpz_clear_randomized(t); - /* apply values */ + /* determine exact the modulus size in bits */ + key_size = mpz_sizeinbase(n, 2); + + /* create and fill in rsa_private_key_t object */ + this = rsa_private_key_create_empty(); + this->k = (key_size + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(n, e); *(this->p) = *p; *(this->q) = *q; *(this->n) = *n; @@ -657,10 +617,8 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size) *(this->exp1) = *exp1; *(this->exp2) = *exp2; *(this->coeff) = *coeff; - - /* set key size in bytes */ - this->k = key_size; - + DBG1("generated %d bit RSA key with keyid: %#B", key_size, &this->keyid); + return &this->public; } @@ -733,17 +691,8 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob) } this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(this->n, this->e); - /* form the keyid as a SHA-1 hash of a publicKeyInfo object */ - { - chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(this->n, this->e); - hasher_t *hasher = hasher_create(HASH_SHA1); - - hasher->allocate_hash(hasher, publicKeyInfo, &this->keyid); - hasher->destroy(hasher); - free(publicKeyInfo.ptr); - } - if (check(this) != SUCCESS) { destroy(this); diff --git a/src/libstrongswan/crypto/rsa/rsa_private_key.h b/src/libstrongswan/crypto/rsa/rsa_private_key.h index e5cf49810..8013f03c2 100644 --- a/src/libstrongswan/crypto/rsa/rsa_private_key.h +++ b/src/libstrongswan/crypto/rsa/rsa_private_key.h @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_private_key.h 3296 2007-10-12 15:23:29Z andreas $ + * RCSID $Id: rsa_private_key.h 3423 2008-01-22 10:32:37Z andreas $ */ #ifndef RSA_PRIVATE_KEY_H_ diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.c b/src/libstrongswan/crypto/rsa/rsa_public_key.c index 6f2158d2b..10af0527e 100644 --- a/src/libstrongswan/crypto/rsa/rsa_public_key.c +++ b/src/libstrongswan/crypto/rsa/rsa_public_key.c @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_public_key.c 3303 2007-10-12 22:49:39Z andreas $ + * RCSID $Id: rsa_public_key.c 3428 2008-01-27 20:58:52Z andreas $ */ #include <gmp.h> @@ -32,6 +34,7 @@ #include "rsa_public_key.h" #include <debug.h> +#include <utils/randomizer.h> #include <crypto/hashers/hasher.h> #include <asn1/asn1.h> #include <asn1/pem.h> @@ -110,8 +113,6 @@ struct private_rsa_public_key_t { chunk_t (*rsavp1) (const private_rsa_public_key_t *this, chunk_t data); }; -private_rsa_public_key_t *rsa_public_key_create_empty(void); - /** * Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1 */ @@ -137,6 +138,55 @@ static chunk_t rsaep(const private_rsa_public_key_t *this, chunk_t data) } /** + * Implementation of rsa_public_key_t.eme_pkcs1_encrypt. + */ +static status_t pkcs1_encrypt(private_rsa_public_key_t *this, + chunk_t in, chunk_t *out) +{ + chunk_t em; + u_char *pos; + int padding = this->k - in.len - 3; + + if (padding < 8) + { + DBG1("rsa padding of %d bytes is too small", padding); + return FAILED; + } + em.len = this->k; + em.ptr = pos = malloc(em.len); + + /* add padding according to PKCS#1 7.2.1 1.+2. */ + *pos++ = 0x00; + *pos++ = 0x02; + + /* pad with pseudo random bytes unequal to zero */ + { + randomizer_t *randomizer = randomizer_create(); + + /* pad with pseudo random bytes unequal to zero */ + while (padding--) + { + randomizer->get_pseudo_random_bytes(randomizer, 1, pos); + while (!*pos) + { + randomizer->get_pseudo_random_bytes(randomizer, 1, pos); + } + pos++; + } + randomizer->destroy(randomizer); + } + + /* append the padding terminator */ + *pos++ = 0x00; + + /* now add the data */ + memcpy(pos, in.ptr, in.len); + *out = this->rsaep(this, em); + free(em.ptr); + return SUCCESS; +} + +/** * Implementation of rsa_public_key.verify_emsa_pkcs1_signature. */ static status_t verify_emsa_pkcs1_signature(const private_rsa_public_key_t *this, @@ -297,19 +347,30 @@ static size_t get_keysize(const private_rsa_public_key_t *this) */ chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e) { - chunk_t rawKey = asn1_wrap(ASN1_SEQUENCE, "mm", + chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_integer_from_mpz(n), asn1_integer_from_mpz(e)); - chunk_t publicKey; - u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING, 1 + rawKey.len); + return asn1_wrap(ASN1_SEQUENCE, "cm", + asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), + asn1_bitstring("m", publicKey)); +} - *pos++ = 0x00; - memcpy(pos, rawKey.ptr, rawKey.len); - free(rawKey.ptr); +/** + * Form the RSA keyid as a SHA-1 hash of a publicKeyInfo object + * Also used in rsa_private_key.c. + */ +chunk_t rsa_public_key_id_create(mpz_t n, mpz_t e) +{ + chunk_t keyid; + chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(n, e); + hasher_t *hasher = hasher_create(HASH_SHA1); + + hasher->allocate_hash(hasher, publicKeyInfo, &keyid); + hasher->destroy(hasher); + free(publicKeyInfo.ptr); - return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_rsaEncryption_id, - publicKey); + return keyid; } /** @@ -328,6 +389,9 @@ static chunk_t get_keyid(const private_rsa_public_key_t *this) return this->keyid; } +/* forward declaration used by rsa_public_key_t.clone */ +private_rsa_public_key_t *rsa_public_key_create_empty(void); + /** * Implementation of rsa_public_key_t.clone. */ @@ -362,6 +426,7 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void) private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t); /* public functions */ + this->public.pkcs1_encrypt = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t*))pkcs1_encrypt; this->public.verify_emsa_pkcs1_signature = (status_t (*) (const rsa_public_key_t*,hash_algorithm_t,chunk_t,chunk_t))verify_emsa_pkcs1_signature; this->public.get_modulus = (mpz_t *(*) (const rsa_public_key_t*))get_modulus; this->public.get_keysize = (size_t (*) (const rsa_public_key_t*))get_keysize; @@ -380,6 +445,20 @@ private_rsa_public_key_t *rsa_public_key_create_empty(void) /* * See header */ +rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e) +{ + private_rsa_public_key_t *this = rsa_public_key_create_empty(); + + mpz_init_set(this->n, n); + mpz_init_set(this->e, e); + + this->k = (mpz_sizeinbase(n, 2) + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(n, e); + return &this->public; +} +/* + * See header + */ rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob) { asn1_ctx_t ctx; @@ -412,19 +491,9 @@ rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob) } objectID++; } - - this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8; - - /* form the keyid as a SHA-1 hash of a publicKeyInfo object */ - { - chunk_t publicKeyInfo = rsa_public_key_info_to_asn1(this->n, this->e); - hasher_t *hasher = hasher_create(HASH_SHA1); - - hasher->allocate_hash(hasher, publicKeyInfo, &this->keyid); - hasher->destroy(hasher); - free(publicKeyInfo.ptr); - } + this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; + this->keyid = rsa_public_key_id_create(this->n, this->e); return &this->public; } diff --git a/src/libstrongswan/crypto/rsa/rsa_public_key.h b/src/libstrongswan/crypto/rsa/rsa_public_key.h index 0a40c2204..c0bd3e351 100644 --- a/src/libstrongswan/crypto/rsa/rsa_public_key.h +++ b/src/libstrongswan/crypto/rsa/rsa_public_key.h @@ -6,8 +6,10 @@ */ /* - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter + * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2007-2008 Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +22,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: rsa_public_key.h 3303 2007-10-12 22:49:39Z andreas $ + * RCSID $Id: rsa_public_key.h 3423 2008-01-22 10:32:37Z andreas $ */ #ifndef RSA_PUBLIC_KEY_H_ @@ -40,20 +42,29 @@ typedef struct rsa_public_key_t rsa_public_key_t; * the EMSA encoding (see PKCS1) * * @b Constructors: + * - rsa_public_key_create() * - rsa_public_key_create_from_chunk() * - rsa_public_key_create_from_file() - * - rsa_private_key_t.get_public_key() - * - * @see rsa_private_key_t - * - * @todo Implement getkey() and savekey() - * + * * @ingroup rsa */ struct rsa_public_key_t { /** - * @brief Verify a EMSA-PKCS1 encodined signature. + * @brief Encrypt a data block using EME-PKCS1 encoding. + * + * + * @param this calling object + * @param data plaintext input data + * @param out encrypted output data + * @return + * - SUCCESS + * - FAILED if data block is too large + */ + status_t (*pkcs1_encrypt) (rsa_public_key_t *this, chunk_t in, chunk_t *out); + + /** + * @brief Verify an EMSA-PKCS1 encoded signature. * * Processes the supplied signature with the RSAVP1 function, * selects the hash algorithm form the resultign ASN1-OID and @@ -123,6 +134,17 @@ struct rsa_public_key_t { }; /** + * @brief Create a RSA public key from modulus and public exponent. + * + * @param n modulus + * @param e public exponent + * @return created rsa_public_key_t + * + * @ingroup rsa + */ +rsa_public_key_t *rsa_public_key_create(mpz_t n, mpz_t e); + +/** * @brief Load an RSA public key from a chunk. * * Load a key from a chunk, encoded in the more frequently diff --git a/src/libstrongswan/crypto/x509.c b/src/libstrongswan/crypto/x509.c index 6f154b36f..eadf11327 100755 --- a/src/libstrongswan/crypto/x509.c +++ b/src/libstrongswan/crypto/x509.c @@ -9,8 +9,8 @@ * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss * Copyright (C) 2002 Mario Strasser - * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * Copyright (C) 2006 Martin Willi, Andreas Steffen + * Copyright (C) 2006 Martin Willi + * Copyright (C) 2000-2008 Andreas Steffen * * Hochschule fuer Technik Rapperswil * @@ -24,7 +24,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: x509.c 3355 2007-11-20 12:06:40Z martin $ + * RCSID $Id: x509.c 3423 2008-01-22 10:32:37Z andreas $ */ #include <gmp.h> @@ -514,7 +514,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0) id_type = ID_DER_ASN1_DN; break; case GN_OBJ_IP_ADDRESS: - id_type = ID_IPV4_ADDR; + id_type = (object.len == 4)? ID_IPV4_ADDR : ID_IPV6_ADDR; break; case GN_OBJ_OTHER_NAME: if (!parse_otherName(object, level + 1)) @@ -1243,6 +1243,22 @@ static void list(private_x509_t *this, FILE *out, bool utc) } } +/** + * Implements x509_t.add_subjectAltNames. + */ +static void add_subjectAltNames(private_x509_t *this, linked_list_t *subjectAltNames) +{ + iterator_t *iterator = subjectAltNames->create_iterator(subjectAltNames, TRUE); + identification_t *name = NULL; + + while (iterator->iterate(iterator, (void**)&name)) + { + name = name->clone(name); + this->subjectAltNames->insert_last(this->subjectAltNames, (void*)name); + } + iterator->destroy(iterator); +} + /* * Defined in header. */ @@ -1251,12 +1267,13 @@ chunk_t x509_build_generalNames(linked_list_t *list) linked_list_t *generalNames = linked_list_create(); iterator_t *iterator = list->create_iterator(list, TRUE); identification_t *name; + chunk_t names = chunk_empty; size_t len = 0; while (iterator->iterate(iterator, (void**)&name)) { asn1_t asn1_type = ASN1_EOC; - chunk_t *generalName = malloc_thing(chunk_t); + chunk_t *generalName; switch (name->get_type(name)) { @@ -1273,22 +1290,24 @@ chunk_t x509_build_generalNames(linked_list_t *list) asn1_type = ASN1_CONTEXT_S_6; break; case ID_IPV4_ADDR: + case ID_IPV6_ADDR: asn1_type = ASN1_CONTEXT_S_7; break; default: continue; } + generalName = malloc_thing(chunk_t); *generalName = asn1_simple_object(asn1_type, name->get_encoding(name)); len += generalName->len; - generalNames->insert_last(generalNames, generalName); + generalNames->insert_last(generalNames, (void*)generalName); } iterator->destroy(iterator); if (len > 0) { iterator_t *iterator = generalNames->create_iterator(generalNames, TRUE); - chunk_t names, *generalName; + chunk_t *generalName; u_char *pos = build_asn1_object(&names, ASN1_SEQUENCE, len); while (iterator->iterate(iterator, (void**)&generalName)) @@ -1299,14 +1318,9 @@ chunk_t x509_build_generalNames(linked_list_t *list) free(generalName); } iterator->destroy(iterator); - generalNames->destroy(generalNames); - - return asn1_wrap(ASN1_OCTET_STRING, "m", names); - } - else - { - return chunk_empty; } + generalNames->destroy(generalNames); + return names; } /* @@ -1330,11 +1344,54 @@ chunk_t x509_build_subjectAltNames(linked_list_t *list) } /** + * Build a to-be-signed X.509 certificate body + */ +static chunk_t x509_build_tbs(private_x509_t *this) +{ + /* version is always X.509v3 */ + chunk_t version = asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2); + + chunk_t extensions = chunk_empty; + + if (this->subjectAltNames->get_count(this->subjectAltNames)) + { + extensions = asn1_wrap(ASN1_CONTEXT_C_3, "m", + asn1_wrap(ASN1_SEQUENCE, "m", + x509_build_subjectAltNames(this->subjectAltNames))); + } + + return asn1_wrap(ASN1_SEQUENCE, "mmccmcmm", + version, + asn1_simple_object(ASN1_INTEGER, this->serialNumber), + asn1_algorithmIdentifier(this->signatureAlgorithm), + this->issuer->get_encoding(this->issuer), + asn1_wrap(ASN1_SEQUENCE, "mm", + timetoasn1(&this->notBefore, ASN1_UTCTIME), + timetoasn1(&this->notAfter, ASN1_UTCTIME) + ), + this->subject->get_encoding(this->subject), + this->public_key->get_publicKeyInfo(this->public_key), + extensions + ); +} + +/** * Implementation of x509_t.build_encoding. */ static void build_encoding(private_x509_t *this, hash_algorithm_t alg, rsa_private_key_t *private_key) { + chunk_t signature; + + this->signatureAlgorithm = hasher_signature_algorithm_to_oid(alg); + this->tbsCertificate = x509_build_tbs(this); + private_key->build_emsa_pkcs1_signature(private_key, alg, + this->tbsCertificate, &signature); + this->signature = asn1_bitstring("m", signature); + this->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm", + this->tbsCertificate, + asn1_algorithmIdentifier(this->signatureAlgorithm), + this->signature); } @@ -1408,6 +1465,7 @@ static private_x509_t *x509_create_empty(void) this->public.create_ocspuri_iterator = (iterator_t* (*) (const x509_t*))create_ocspuri_iterator; this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify; this->public.list = (void (*) (x509_t*, FILE *out, bool utc))list; + this->public.add_subjectAltNames = (void (*) (x509_t*,linked_list_t*))add_subjectAltNames; this->public.build_encoding = (void (*) (x509_t*,hash_algorithm_t,rsa_private_key_t*))build_encoding; this->public.destroy = (void (*) (x509_t*))destroy; @@ -1417,13 +1475,19 @@ static private_x509_t *x509_create_empty(void) /* * Described in header. */ -x509_t *x509_create_(chunk_t serialNumber, identification_t *issuer, identification_t *subject) +x509_t *x509_create(chunk_t serialNumber, identification_t *issuer, + time_t notBefore, time_t notAfter, + identification_t *subject, + rsa_public_key_t *public_key) { private_x509_t *this = x509_create_empty(); this->serialNumber = serialNumber; this->issuer = issuer->clone(issuer); + this->notBefore = notBefore; + this->notAfter = notAfter; this->subject = subject->clone(subject); + this->public_key = public_key->clone(public_key); return &this->public; } diff --git a/src/libstrongswan/crypto/x509.h b/src/libstrongswan/crypto/x509.h index 1ab267dac..def45be6b 100755 --- a/src/libstrongswan/crypto/x509.h +++ b/src/libstrongswan/crypto/x509.h @@ -9,8 +9,8 @@ * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss * Copyright (C) 2002 Mario Strasser - * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * Copyright (C) 2006 Martin Willi, Andreas Steffen + * Copyright (C) 2006 Martin Willi + * Copyright (C) 2000-2008 Andreas Steffen * * Hochschule fuer Technik Rapperswil * @@ -24,7 +24,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: x509.h 3301 2007-10-12 21:56:30Z andreas $ + * RCSID $Id: x509.h 3421 2008-01-22 01:09:19Z andreas $ */ #ifndef X509_H_ @@ -327,6 +327,7 @@ struct x509_t { * @param notBefore start date of validity * @param notAfter end date of validity * @param subject subject distinguished name + * @param public_key public key * * @return created x509_t certificate, or NULL if invalid. * @@ -334,7 +335,8 @@ struct x509_t { */ x509_t *x509_create(chunk_t serialNumber, identification_t *issuer, time_t notBefore, time_t notAfter, - identification_t *subject); + identification_t *subject, + rsa_public_key_t *public_key); /** * @brief Read a X.509 certificate from a DER encoded blob. |