pkcs7: Support rsa-pss signatures
This commit is contained in:
@@ -44,6 +44,11 @@ struct private_pkcs7_signed_data_t {
|
||||
*/
|
||||
container_t *content;
|
||||
|
||||
/**
|
||||
* Signature scheme
|
||||
*/
|
||||
signature_params_t *scheme;
|
||||
|
||||
/**
|
||||
* Encoded PKCS#7 signed-data
|
||||
*/
|
||||
@@ -365,6 +370,7 @@ METHOD(container_t, destroy, void,
|
||||
this->creds->destroy(this->creds);
|
||||
this->signerinfos->destroy_function(this->signerinfos,
|
||||
(void*)signerinfo_destroy);
|
||||
signature_params_destroy(this->scheme);
|
||||
DESTROY_IF(this->content);
|
||||
free(this->encoding.ptr);
|
||||
free(this);
|
||||
@@ -527,31 +533,45 @@ static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
|
||||
{
|
||||
chunk_t authenticatedAttributes = chunk_empty;
|
||||
chunk_t encryptedDigest = chunk_empty;
|
||||
chunk_t data, signerInfo, encoding = chunk_empty;
|
||||
chunk_t messageDigest, signingTime, attributes;
|
||||
signature_scheme_t scheme;
|
||||
chunk_t data = chunk_empty, encoding = chunk_empty;
|
||||
chunk_t digest_alg = chunk_empty, sig_scheme = chunk_empty;
|
||||
chunk_t signerInfo = chunk_empty, messageDigest, signingTime, attributes;
|
||||
hasher_t *hasher;
|
||||
time_t now;
|
||||
int digest_oid;
|
||||
|
||||
digest_oid = hasher_algorithm_to_oid(alg);
|
||||
scheme = signature_scheme_from_oid(digest_oid);
|
||||
|
||||
if (!this->content->get_data(this->content, &data))
|
||||
/* select signature scheme, if not already specified */
|
||||
if (!this->scheme)
|
||||
{
|
||||
INIT(this->scheme,
|
||||
.scheme = signature_scheme_from_oid(
|
||||
hasher_signature_algorithm_to_oid(alg,
|
||||
key->get_type(key))),
|
||||
);
|
||||
}
|
||||
if (this->scheme->scheme == SIGN_UNKNOWN)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!signature_params_build(this->scheme, &sig_scheme))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (!this->content->get_data(this->content, &data))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
hasher = lib->crypto->create_hasher(lib->crypto, alg);
|
||||
if (!hasher || !hasher->allocate_hash(hasher, data, &messageDigest))
|
||||
{
|
||||
DESTROY_IF(hasher);
|
||||
DBG1(DBG_LIB, " hash algorithm %N not support",
|
||||
DBG1(DBG_LIB, " hash algorithm %N not supported",
|
||||
hash_algorithm_names, alg);
|
||||
free(data.ptr);
|
||||
return FALSE;
|
||||
goto err;
|
||||
}
|
||||
chunk_free(&data);
|
||||
hasher->destroy(hasher);
|
||||
|
||||
pkcs9->add_attribute(pkcs9,
|
||||
OID_PKCS9_MESSAGE_DIGEST,
|
||||
asn1_wrap(ASN1_OCTET_STRING, "m", messageDigest));
|
||||
@@ -562,40 +582,38 @@ static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
|
||||
pkcs9->add_attribute(pkcs9, OID_PKCS9_SIGNING_TIME, signingTime);
|
||||
pkcs9->add_attribute(pkcs9, OID_PKCS9_CONTENT_TYPE,
|
||||
asn1_build_known_oid(OID_PKCS7_DATA));
|
||||
|
||||
attributes = pkcs9->get_encoding(pkcs9);
|
||||
|
||||
if (!key->sign(key, scheme, NULL, attributes, &encryptedDigest))
|
||||
if (!key->sign(key, this->scheme->scheme, this->scheme->params, attributes,
|
||||
&encryptedDigest))
|
||||
{
|
||||
free(data.ptr);
|
||||
return FALSE;
|
||||
goto err;
|
||||
}
|
||||
authenticatedAttributes = chunk_clone(attributes);
|
||||
*authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
|
||||
|
||||
free(data.ptr);
|
||||
if (encryptedDigest.ptr)
|
||||
{
|
||||
encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
|
||||
}
|
||||
signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm",
|
||||
|
||||
digest_alg = asn1_algorithmIdentifier(hasher_algorithm_to_oid(alg));
|
||||
signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmmm",
|
||||
ASN1_INTEGER_1,
|
||||
build_issuerAndSerialNumber(cert),
|
||||
asn1_algorithmIdentifier(digest_oid),
|
||||
digest_alg,
|
||||
authenticatedAttributes,
|
||||
asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
|
||||
sig_scheme,
|
||||
encryptedDigest);
|
||||
sig_scheme = chunk_empty;
|
||||
|
||||
if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
|
||||
{
|
||||
free(signerInfo.ptr);
|
||||
return FALSE;
|
||||
goto err;
|
||||
}
|
||||
if (!this->content->get_encoding(this->content, &data))
|
||||
{
|
||||
free(encoding.ptr);
|
||||
free(signerInfo.ptr);
|
||||
return FALSE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
this->encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
|
||||
@@ -603,15 +621,22 @@ static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
|
||||
asn1_wrap(ASN1_CONTEXT_C_0, "m",
|
||||
asn1_wrap(ASN1_SEQUENCE, "cmmmm",
|
||||
ASN1_INTEGER_1,
|
||||
asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_oid)),
|
||||
asn1_wrap(ASN1_SET, "m", digest_alg),
|
||||
data,
|
||||
asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding),
|
||||
asn1_wrap(ASN1_SET, "m", signerInfo))));
|
||||
|
||||
|
||||
pkcs9->destroy(pkcs9);
|
||||
/* TODO: create signerInfos entry */
|
||||
return TRUE;
|
||||
|
||||
err:
|
||||
chunk_free(&data);
|
||||
chunk_free(&digest_alg);
|
||||
chunk_free(&sig_scheme);
|
||||
chunk_free(&signerInfo);
|
||||
chunk_free(&encoding);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -621,7 +646,8 @@ pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
|
||||
{
|
||||
private_pkcs7_signed_data_t *this;
|
||||
chunk_t blob = chunk_empty;
|
||||
hash_algorithm_t alg = HASH_SHA1;
|
||||
hash_algorithm_t alg = HASH_SHA256;
|
||||
signature_params_t *scheme = NULL;
|
||||
private_key_t *key = NULL;
|
||||
certificate_t *cert = NULL;
|
||||
pkcs7_attributes_t *pkcs9;
|
||||
@@ -646,6 +672,9 @@ pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
|
||||
case BUILD_BLOB:
|
||||
blob = va_arg(args, chunk_t);
|
||||
continue;
|
||||
case BUILD_SIGNATURE_SCHEME:
|
||||
scheme = va_arg(args, signature_params_t*);
|
||||
continue;
|
||||
case BUILD_PKCS7_ATTRIBUTE:
|
||||
oid = va_arg(args, int);
|
||||
value = va_arg(args, chunk_t);
|
||||
@@ -663,11 +692,11 @@ pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
|
||||
{
|
||||
this = create_empty();
|
||||
|
||||
this->scheme = signature_params_clone(scheme);
|
||||
this->creds->add_cert(this->creds, FALSE, cert->get_ref(cert));
|
||||
this->content = lib->creds->create(lib->creds,
|
||||
CRED_CONTAINER, CONTAINER_PKCS7_DATA,
|
||||
BUILD_BLOB, blob, BUILD_END);
|
||||
|
||||
if (this->content && generate(this, key, cert, alg, pkcs9))
|
||||
{
|
||||
return &this->public;
|
||||
|
||||
@@ -465,7 +465,7 @@ static int scep()
|
||||
/* build pkcs7 request */
|
||||
pkcs7_req = scep_build_request(pkcs10_encoding, transID, scep_msg_type,
|
||||
x509_ca_enc, cipher, key_size, x509_signer,
|
||||
digest_alg, priv_signer);
|
||||
digest_alg, scheme, priv_signer);
|
||||
if (!pkcs7_req.ptr)
|
||||
{
|
||||
DBG1(DBG_APP, "failed to build SCEP request");
|
||||
@@ -525,7 +525,7 @@ static int scep()
|
||||
|
||||
certPoll = scep_build_request(issuerAndSubject, transID, SCEP_CertPoll_MSG,
|
||||
x509_ca_enc, cipher, key_size, x509_signer,
|
||||
digest_alg, priv_signer);
|
||||
digest_alg, scheme, priv_signer);
|
||||
if (!certPoll.ptr)
|
||||
{
|
||||
DBG1(DBG_APP, "failed to build SCEP certPoll request");
|
||||
|
||||
+3
-1
@@ -163,7 +163,8 @@ bool scep_generate_transaction_id(public_key_t *public,
|
||||
chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
|
||||
certificate_t *enc_cert, encryption_algorithm_t enc_alg,
|
||||
size_t key_size, certificate_t *signer_cert,
|
||||
hash_algorithm_t digest_alg, private_key_t *private_key)
|
||||
hash_algorithm_t digest_alg, signature_params_t *scheme,
|
||||
private_key_t *private_key)
|
||||
{
|
||||
chunk_t request;
|
||||
container_t *container;
|
||||
@@ -212,6 +213,7 @@ chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
|
||||
BUILD_SIGNING_CERT, signer_cert,
|
||||
BUILD_SIGNING_KEY, private_key,
|
||||
BUILD_DIGEST_ALG, digest_alg,
|
||||
BUILD_SIGNATURE_SCHEME, scheme,
|
||||
BUILD_PKCS7_ATTRIBUTE, OID_PKI_SENDER_NONCE, senderNonce,
|
||||
BUILD_PKCS7_ATTRIBUTE, OID_PKI_TRANS_ID, transID,
|
||||
BUILD_PKCS7_ATTRIBUTE, OID_PKI_MESSAGE_TYPE, msgType,
|
||||
|
||||
+2
-1
@@ -108,7 +108,8 @@ bool scep_generate_transaction_id(public_key_t *key,
|
||||
chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
|
||||
certificate_t *enc_cert, encryption_algorithm_t enc_alg,
|
||||
size_t key_size, certificate_t *signer_cert,
|
||||
hash_algorithm_t digest_alg, private_key_t *private_key);
|
||||
hash_algorithm_t digest_alg, signature_params_t *scheme,
|
||||
private_key_t *private_key);
|
||||
|
||||
/**
|
||||
* Send a SCEP request via HTTP and wait for a response
|
||||
|
||||
Reference in New Issue
Block a user