From 99c166a1b0408e6d5c6efdc402fa859652048751 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Wed, 11 Nov 2020 17:50:17 +1000 Subject: [PATCH] Add docs for ASN1_item_sign and ASN1_item_verify functions This is to address part of issue #13192. Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/13373) --- doc/man3/ASN1_item_sign.pod | 226 ++++++++++++++++++++++++++++++++++++ util/missingcrypto.txt | 6 - 2 files changed, 226 insertions(+), 6 deletions(-) create mode 100644 doc/man3/ASN1_item_sign.pod diff --git a/doc/man3/ASN1_item_sign.pod b/doc/man3/ASN1_item_sign.pod new file mode 100644 index 0000000000..407268bf17 --- /dev/null +++ b/doc/man3/ASN1_item_sign.pod @@ -0,0 +1,226 @@ +=pod + +=head1 NAME + +ASN1_item_sign, ASN1_item_sign_ex, ASN1_item_sign_ctx, +ASN1_item_verify, ASN1_item_verify_ex, ASN1_item_verify_ctx - +ASN1 sign and verify + +=head1 SYNOPSIS + + #include + + int ASN1_item_sign_ex(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + const void *data, const ASN1_OCTET_STRING *id, + EVP_PKEY *pkey, const EVP_MD *md, OSSL_LIB_CTX *libctx, + const char *propq); + + int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, const void *data, + EVP_PKEY *pkey, const EVP_MD *md); + + int ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, + X509_ALGOR *algor2, ASN1_BIT_STRING *signature, + const void *data, EVP_MD_CTX *ctx); + + int ASN1_item_verify_ex(const ASN1_ITEM *it, const X509_ALGOR *alg, + const ASN1_BIT_STRING *signature, const void *data, + const ASN1_OCTET_STRING *id, EVP_PKEY *pkey, + OSSL_LIB_CTX *libctx, const char *propq); + + int ASN1_item_verify(const ASN1_ITEM *it, const X509_ALGOR *alg, + const ASN1_BIT_STRING *signature, const void *data, + EVP_PKEY *pkey); + + int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg, + const ASN1_BIT_STRING *signature, const void *data, + EVP_MD_CTX *ctx); + +=head1 DESCRIPTION + +ASN1_item_sign_ex() is used to sign arbitrary ASN1 data using a data object +I, the ASN.1 structure I, private key I and message digest I. +The data that is signed is formed by taking the data object in I and +converting it to der format using the ASN.1 structure I. +The I that will be signed, and a structure containing the signature may +both have a copy of the B. The ASN1_item_sign_ex() function will +write the correct B to the structs based on the algorithms and +parameters that have been set up. If one of I or I points to the +B of the I to be signed, then that B will first be +written before the signature is generated. +Examples of valid values that can be used by the ASN.1 structure I are +ASN1_ITEM_rptr(X509_CINF), ASN1_ITEM_rptr(X509_REQ_INFO) and +ASN1_ITEM_rptr(X509_CRL_INFO). +The B specified in I and the property query string +specified in I are used when searching for algorithms in providers. +The generated signature is set into I. +The optional parameter I can be NULL, but can be set for special key types. +See EVP_PKEY_CTX_set1_id() for further info. The output parameters and +I are ignored if they are NULL. + +ASN1_item_sign() is similar to ASN1_item_sign_ex() but uses default values of +NULL for the I, I and I. + +ASN1_item_sign_ctx() is similiar to ASN1_item_sign() but uses the parameters +contained in digest context I. + +ASN1_item_verify_ex() is used to verify the signature I of internal +data I using the public key I and algorithm identifier I. +The data that is verified is formed by taking the data object in I and +converting it to der format using the ASN.1 structure I. +The B specified in I and the property query string +specified in I are used when searching for algorithms in providers. +The optional parameter I can be NULL, but can be set for special key types. +See EVP_PKEY_CTX_set1_id() for further info. + +ASN1_item_verify() is similar to ASN1_item_verify_ex() but uses default values of +NULL for the I, I and I. + +ASN1_item_verify_ctx() is similiar to ASN1_item_verify() but uses the parameters +contained in digest context I. + + +=head1 RETURN VALUES + +All sign functions return the size of the signature in bytes for success and +zero for failure. + +All verify functions return 1 if the signature is valid and 0 if the signature +check fails. If the signature could not be checked at all because it was +ill-formed or some other error occurred then -1 is returned. + +=head1 EXAMPLES + +In the following example a 'MyObject' object is signed using the key contained +in an EVP_MD_CTX. The signature is written to MyObject.signature. The object is +then output in DER format and then loaded back in and verified. + + #include + #include + + /* An object used to store the ASN1 data fields that will be signed */ + typedef struct MySignInfoObject_st + { + ASN1_INTEGER *version; + X509_ALGOR sig_alg; + } MySignInfoObject; + + DECLARE_ASN1_FUNCTIONS(MySignInfoObject) + /* + * A higher level object containing the ASN1 fields, signature alg and + * output signature. + */ + typedef struct MyObject_st + { + MySignInfoObject info; + X509_ALGOR sig_alg; + ASN1_BIT_STRING *signature; + } MyObject; + + DECLARE_ASN1_FUNCTIONS(MyObject) + + /* The ASN1 definition of MySignInfoObject */ + ASN1_SEQUENCE_cb(MySignInfoObject, NULL) = { + ASN1_SIMPLE(MySignInfoObject, version, ASN1_INTEGER) + ASN1_EMBED(MySignInfoObject, sig_alg, X509_ALGOR), + } ASN1_SEQUENCE_END_cb(MySignInfoObject, MySignInfoObject) + + /* new, free, d2i & i2d functions for MySignInfoObject */ + IMPLEMENT_ASN1_FUNCTIONS(MySignInfoObject) + + /* The ASN1 definition of MyObject */ + ASN1_SEQUENCE_cb(MyObject, NULL) = { + ASN1_EMBED(MyObject, info, MySignInfoObject), + ASN1_EMBED(MyObject, sig_alg, X509_ALGOR), + ASN1_SIMPLE(MyObject, signature, ASN1_BIT_STRING) + } ASN1_SEQUENCE_END_cb(MyObject, MyObject) + + /* new, free, d2i & i2d functions for MyObject */ + IMPLEMENT_ASN1_FUNCTIONS(MyObject) + + int test_asn1_item_sign_verify(const char *mdname, EVP_PKEY *pkey, long version) + { + int ret = 0; + unsigned char *obj_der = NULL; + const unsigned char *p = NULL; + MyObject *obj = NULL, *loaded_obj = NULL; + const ASN1_ITEM *it = ASN1_ITEM_rptr(MySignInfoObject); + EVP_MD_CTX *sctx = NULL, *vctx = NULL; + int len; + + /* Create MyObject and set its version */ + obj = MyObject_new(); + if (obj == NULL) + goto err; + if (!ASN1_INTEGER_set(obj->info.version, version)) + goto err; + + /* Set the key and digest used for signing */ + sctx = EVP_MD_CTX_new(); + if (sctx == NULL + || !EVP_DigestSignInit_ex(sctx, NULL, mdname, NULL, NULL, pkey)) + goto err; + + /* + * it contains the mapping between ASN.1 data and an object MySignInfoObject + * obj->info is the 'MySignInfoObject' object that will be + * converted into DER data and then signed. + * obj->signature will contain the output signature. + * obj->sig_alg is filled with the private key's signing algorithm id. + * obj->info.sig_alg is another copy of the signing algorithm id that sits + * within MyObject. + */ + len = ASN1_item_sign_ctx(it, &obj->sig_alg, &obj->info.sig_alg, + obj->signature, &obj->info, sctx); + if (len <= 0 + || X509_ALGOR_cmp(&obj->sig_alg, &obj->info.sig_alg) != 0) + goto err; + + /* Output MyObject in der form */ + len = i2d_MyObject(obj, &obj_der); + if (len <= 0) + goto err; + + /* Set the key and digest used for verifying */ + vctx = EVP_MD_CTX_new(); + if (vctx == NULL + || !EVP_DigestVerifyInit_ex(vctx, NULL, mdname, NULL, NULL, pkey)) + goto err; + + /* Load the der data back into an object */ + p = obj_der; + loaded_obj = d2i_MyObject(NULL, &p, len); + if (loaded_obj == NULL) + goto err; + /* Verify the loaded object */ + ret = ASN1_item_verify_ctx(it, &loaded_obj->sig_alg, loaded_obj->signature, + &loaded_obj->info, vctx); +err: + OPENSSL_free(obj_der); + MyObject_free(loaded_obj); + MyObject_free(obj); + EVP_MD_CTX_free(sctx); + EVP_MD_CTX_free(vctx); + return ret; + } + +=head1 SEE ALSO + +L, +L + +=head1 HISTORY + +ASN1_item_sign_ex() and ASN1_item_verify_ex() were added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index 169aab1bd6..85f03fc9cc 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -154,13 +154,7 @@ ASN1_item_ndef_i2d(3) ASN1_item_new(3) ASN1_item_pack(3) ASN1_item_print(3) -ASN1_item_sign(3) -ASN1_item_sign_ctx(3) -ASN1_item_sign_ex(3) ASN1_item_unpack(3) -ASN1_item_verify(3) -ASN1_item_verify_ctx(3) -ASN1_item_verify_ex(3) ASN1_mbstring_copy(3) ASN1_mbstring_ncopy(3) ASN1_object_size(3)