4 #include <openssl/bio.h>
5 #include <openssl/cms.h>
6 #include <openssl/crypto.h>
7 #include <openssl/err.h>
8 #include <openssl/evp.h>
9 #include <openssl/pkcs7.h>
10 #include <openssl/x509.h>
12 #include "isds_priv.h"
16 #ifndef SHA1_DIGEST_LENGTH
17 # define SHA1_DIGEST_LENGTH 20
18 #endif /* !SHA1_DIGEST_LENGTH */
20 #if OPENSSL_VERSION_NUMBER < 0x10100000L
21 static EVP_MD_CTX
*EVP_MD_CTX_new(void) {
22 EVP_MD_CTX
*mdctx
= malloc(sizeof(*mdctx
));
24 EVP_MD_CTX_init(mdctx
);
29 static void EVP_MD_CTX_free(EVP_MD_CTX
*mdctx
) {
30 EVP_MD_CTX_cleanup(mdctx
);
35 /* Initialise all cryptographic libraries which libisds depends on.
36 * @return IE_SUCCESS if everything went all-right. */
37 _hidden isds_error
_isds_init_crypto(void)
39 OpenSSL_add_all_digests(); /* Loads all digest algorithms. */
41 ERR_load_crypto_strings();
42 //ERR_load_CMS_strings();
44 version_openssl
= SSLeay_version(SSLEAY_VERSION
);
49 /* Computes hash from @input with @length and store it into @hash.
50 * The hash algorithm is defined inside @hash.
51 * @input is input block to hash
52 * @length is @input block length in bytes
53 * @hash input algorithm, output hash value and hash length; hash value will be
54 * reallocated, it's always valid pointer or NULL (before and after call) */
55 _hidden isds_error
_isds_compute_hash(const void *input
,
56 const size_t length
, struct isds_hash
*hash
)
58 isds_error retval
= IE_SUCCESS
;
59 void *hash_buf
= NULL
;
61 EVP_MD_CTX
*mdctx
= NULL
;
62 const char *hash_name
= NULL
;
66 if (((0 != length
) && (NULL
== input
)) || (NULL
== hash
)) {
70 isds_log(ILF_SEC
, ILL_DEBUG
,
71 _("Data hash requested, length=%zu, content:\n%*s\n"
72 "End of data to hash\n"), length
, length
, input
);
74 /* Select algorithm */
75 switch (hash
->algorithm
) {
76 case HASH_ALGORITHM_MD5
: hash_name
= "MD5"; break;
77 case HASH_ALGORITHM_SHA_1
: hash_name
= "SHA1"; break;
78 case HASH_ALGORITHM_SHA_224
: hash_name
= "SHA224"; break;
79 case HASH_ALGORITHM_SHA_256
: hash_name
= "SHA256"; break;
80 case HASH_ALGORITHM_SHA_384
: hash_name
= "SHA384"; break;
81 case HASH_ALGORITHM_SHA_512
: hash_name
= "SHA512"; break;
87 md
= EVP_get_digestbyname(hash_name
);
93 mdctx
= EVP_MD_CTX_new();
98 if (!EVP_DigestInit(mdctx
, md
)) {
102 if (!EVP_DigestUpdate(mdctx
, input
, length
)) {
107 hash_len
= EVP_MD_size(md
);
108 hash_buf
= realloc(hash
->value
, hash_len
);
109 if (NULL
== hash_buf
) {
113 hash
->value
= hash_buf
;
114 hash
->length
= hash_len
;
116 if (!EVP_DigestFinal_ex(mdctx
, hash
->value
, &md_len
)) {
121 EVP_MD_CTX_free(mdctx
);
128 EVP_MD_CTX_free(mdctx
);
133 /* Free CMS data buffer allocated inside _isds_extract_cms_data().
134 * This is necessary because GPGME.
135 * @buffer is pointer to memory to free */
136 _hidden
void _isds_cms_data_free(void *buffer
)
141 /* Extract data from CMS (successor of PKCS#7)
142 * The CMS' signature is is not verified.
143 * @context is session context
144 * @cms is input block with CMS structure
145 * @cms_length is @cms block length in bytes
146 * @data are automatically reallocated bit stream with data found in @cms
147 * You must free them with _isds_cms_data_free().
148 * @data_length is length of @data in bytes */
149 _hidden isds_error
_isds_extract_cms_data(struct isds_ctx
*context
,
150 const void *cms
, const size_t cms_length
,
151 void **data
, size_t *data_length
)
154 isds_error retval
= IE_SUCCESS
;
156 CMS_ContentInfo
*cms_ci
= NULL
;
157 const ASN1_OBJECT
*asn1_obj
;
158 ASN1_OCTET_STRING
**pos
;
162 assert(NULL
!= context
);
164 if ((NULL
== cms
) || (0 == cms_length
) ||
165 (NULL
== data
) || (NULL
== data_length
)) {
172 bio
= BIO_new_mem_buf((void *) cms
, cms_length
);
174 isds_log_message(context
, _("Creating CMS reader BIO failed"));
175 while (0 != (err
= ERR_get_error())) {
176 locale_str
= _isds_utf82locale(ERR_error_string(err
, NULL
));
177 if (NULL
!= locale_str
) {
178 isds_log_message(context
, locale_str
);
186 cms_ci
= d2i_CMS_bio(bio
, NULL
);
187 if (NULL
== cms_ci
) {
188 isds_log_message(context
, _("Cannot parse CMS"));
189 while (0 != (err
= ERR_get_error())) {
190 locale_str
= _isds_utf82locale(ERR_error_string(err
, NULL
));
191 if (NULL
!= locale_str
) {
192 isds_log_message(context
, locale_str
);
200 BIO_free(bio
); bio
= NULL
;
202 asn1_obj
= CMS_get0_type(cms_ci
);
203 nid
= OBJ_obj2nid(asn1_obj
);
206 case NID_id_smime_ct_compressedData
:
207 case NID_id_smime_ct_authData
:
208 case NID_pkcs7_enveloped
:
209 case NID_pkcs7_encrypted
:
210 case NID_pkcs7_digest
:
215 case NID_pkcs7_signed
:
224 pos
= CMS_get0_content(cms_ci
);
225 if ((NULL
== pos
) || (NULL
== *pos
)) {
231 *data
= malloc((*pos
)->length
);
236 *data_length
= (*pos
)->length
;
237 memcpy(*data
, (*pos
)->data
, (*pos
)->length
);
239 CMS_ContentInfo_free(cms_ci
); cms_ci
= NULL
;
247 if (NULL
!= cms_ci
) {
248 CMS_ContentInfo_free(cms_ci
);