1 /* zxsig.c - Signature generation and validation
2 * Copyright (c) 2010 Sampo Kellomaki (sampo@iki.fi), All Rights Reserved.
3 * Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved.
4 * Copyright (c) 2015-2016 Synergetics (sampo@synergetics.be), All Rights Reserved.
5 * Author: Sampo Kellomaki (sampo@iki.fi)
6 * This is confidential unpublished proprietary source code of the author.
7 * NO WARRANTY, not even implied warranties. Contains trade secrets.
8 * Distribution prohibited unless authorized in writing.
9 * Licensed under Apache License 2.0, see file COPYING.
10 * $Id: zxsig.c,v 1.29 2010-01-08 02:10:09 sampo Exp $
11 *
12 * 29.9.2006, created --Sampo
13 * 23.9.2007, added XML ENC support --Sampo
14 * 8.10.2007, added XML signing support --Sampo
15 * 4.10.2008, improved documentation --Sampo
16 * 1.12.2010, improved logging of canonicalizations --Sampo
17 * 16.10.2015, upgraded sha256 support --Sampo
18 * 18.12.2015, applied patch from soconnor, perceptyx, adding algos --Sampo
19 * 7.1.2016, made hash algorithm for generated signatures more configurable --Sampo
20 *
21 * See paper: Tibor Jager, Kenneth G. Paterson, Juraj Somorovsky: "One Bad Apple: Backwards Compatibility Attacks on State-of-the-Art Cryptography", 2013 http://www.nds.ruhr-uni-bochum.de/research/publications/backwards-compatibility/ /t/BackwardsCompatibilityAttacks.pdf
22 */
23
24 #include "platform.h"
25 #include "errmac.h"
26
27 #include <memory.h>
28 #include <string.h>
29
30 #ifdef USE_OPENSSL
31 #include <openssl/x509.h>
32 #include <openssl/sha.h>
33 #include <openssl/md5.h>
34 #include <openssl/evp.h>
35 #include <openssl/rsa.h>
36 #include <openssl/dsa.h>
37 #include <openssl/err.h>
38 #endif
39
40 #include "zx.h"
41 #include "zxid.h"
42 #include "zxidutil.h"
43 #include "zxidconf.h"
44 #include "c/zx-data.h" /* For the XMLDSIG code. */
45 #include "c/zx-const.h"
46
47 ZXID_DECL struct zx_ds_KeyInfo_s* zxid_key_info(zxid_conf* cf, struct zx_elem_s* father, X509* x);
48
49 /*(-) Heuristic guesser for extracting hash algorithm name
50 * Input is an algorithm URL like "http://www.w3.org/2001/04/xmldsig-more%23rsa-sha384"
51 * or "http://www.w3.org/2000/09/xmldsig#sha1" or an OpenSSL algorithm
52 * string like "sha384WithRSAEncryption" or "dsa_with_SHA256".
53 * If dsp is nonnull, it is populated with the corresponding digest URL. */
54
zxsig_extract_hash_algo(const char * spec,const char ** dsp)55 static const char* zxsig_extract_hash_algo(const char* spec, const char** dsp)
56 {
57 if (!spec || strstr(spec, "sha1") || strstr(spec, "SHA1")) if (dsp) *dsp = DIGEST_ALGO_SHA1; return "SHA1";
58 if (strstr(spec, "sha224") || strstr(spec, "SHA224")) if (dsp) *dsp = DIGEST_ALGO_SHA224; return "SHA224";
59 if (strstr(spec, "sha256") || strstr(spec, "SHA256")) if (dsp) *dsp = DIGEST_ALGO_SHA256; return "SHA256";
60 if (strstr(spec, "sha384") || strstr(spec, "SHA384")) if (dsp) *dsp = DIGEST_ALGO_SHA384; return "SHA384";
61 if (strstr(spec, "sha512") || strstr(spec, "SHA512")) if (dsp) *dsp = DIGEST_ALGO_SHA512; return "SHA512";
62 if (strstr(spec, "sha2") || strstr(spec, "SHA2")) if (dsp) *dsp = DIGEST_ALGO_SHA256; return "SHA256";
63 ERR("Could not determine hash algorithm from spec(%s)", spec);
64 if (dsp) *dsp = "err";
65 return 0;
66 }
67
68 /*(-) Heuristic to construct SIG_ALGO URL string based on chosen digest and algo pr private key */
zxsig_choose_xmldsig_sig_meth_url(EVP_PKEY * priv_key,const char * dig_alg)69 const char* zxsig_choose_xmldsig_sig_meth_url(EVP_PKEY* priv_key, const char* dig_alg)
70 {
71 switch (EVP_PKEY_type(priv_key->type)) {
72 case EVP_PKEY_RSA:
73 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_RSA_SHA1;
74 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_RSA_SHA224;
75 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_RSA_SHA256;
76 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_RSA_SHA384;
77 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_RSA_SHA512;
78 break;
79 case EVP_PKEY_DSA:
80 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_DSA_SHA1;
81 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_DSA_SHA224;
82 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_DSA_SHA256;
83 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_DSA_SHA384;
84 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_DSA_SHA512;
85 break;
86 case EVP_PKEY_EC:
87 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_ECDSA_SHA1;
88 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_ECDSA_SHA224;
89 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_ECDSA_SHA256;
90 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_ECDSA_SHA384;
91 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_ECDSA_SHA512;
92 break;
93 #if 0
94 /* *** can not find documentation for these */
95 case EVP_PKEY_DH:
96 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_DH_SHA1;
97 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_DH_SHA224;
98 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_DH_SHA256;
99 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_DH_SHA384;
100 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_DH_SHA512;
101 break;
102 #endif
103 default:
104 ERR("Unknown private key type=%x", EVP_PKEY_type(priv_key->type));
105 return "#pkerr";
106 }
107 ERR("Unknown digest algo(%s)", STRNULLCHKQ(dig_alg));
108 return "#digerr";
109 }
110
111 /*(-) Heuristic to construct SIG_ALGO URL string based on chosen digest and algo pr private key */
zxsig_choose_xmldsig_sig_meth_urlenc(EVP_PKEY * priv_key,const char * dig_alg)112 const char* zxsig_choose_xmldsig_sig_meth_urlenc(EVP_PKEY* priv_key, const char* dig_alg)
113 {
114 switch (EVP_PKEY_type(priv_key->type)) {
115 case EVP_PKEY_RSA:
116 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_RSA_SHA1_URLENC;
117 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_RSA_SHA224_URLENC;
118 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_RSA_SHA256_URLENC;
119 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_RSA_SHA384_URLENC;
120 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_RSA_SHA512_URLENC;
121 break;
122 case EVP_PKEY_DSA:
123 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_DSA_SHA1_URLENC;
124 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_DSA_SHA224_URLENC;
125 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_DSA_SHA256_URLENC;
126 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_DSA_SHA384_URLENC;
127 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_DSA_SHA512_URLENC;
128 break;
129 case EVP_PKEY_EC:
130 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_ECDSA_SHA1_URLENC;
131 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_ECDSA_SHA224_URLENC;
132 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_ECDSA_SHA256_URLENC;
133 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_ECDSA_SHA384_URLENC;
134 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_ECDSA_SHA512_URLENC;
135 break;
136 #if 0
137 /* *** can not find documentation for these */
138 case EVP_PKEY_DH:
139 if (!strcmp(dig_alg, "SHA1")) return SIG_ALGO_DH_SHA1_URLENC;
140 if (!strcmp(dig_alg, "SHA224")) return SIG_ALGO_DH_SHA224_URLENC;
141 if (!strcmp(dig_alg, "SHA256")) return SIG_ALGO_DH_SHA256_URLENC;
142 if (!strcmp(dig_alg, "SHA384")) return SIG_ALGO_DH_SHA384_URLENC;
143 if (!strcmp(dig_alg, "SHA512")) return SIG_ALGO_DH_SHA512_URLENC;
144 break;
145 #endif
146 default:
147 ERR("Unknown private key type=%x", EVP_PKEY_type(priv_key->type));
148 return "#pkerr";
149 }
150 ERR("Unknown digest algo(%s)", STRNULLCHKQ(dig_alg));
151 return "#digerr";
152 }
153
154 #if 0
155 /* *** these are no longer needed as selection is handled by configuration system */
156 const char* zxid_get_cert_signature_algo_url(X509* cert)
157 {
158 const char* alg = zxid_get_cert_signature_algo(cert);
159 if (!alg || !strcmp(alg, "")) return SIG_ALGO;
160 if (!strcmp(alg, "sha1WithRSAEncryption")) return SIG_ALGO_RSA_SHA1;
161 if (!strcmp(alg, "dsaWithSHA1")) return SIG_ALGO_DSA_SHA1;
162 if (!strcmp(alg, "sha224WithRSAEncryption")) return SIG_ALGO_RSA_SHA224;
163 if (!strcmp(alg, "sha224WithDSAEncryption")) return SIG_ALGO;
164 if (!strcmp(alg, "sha256WithRSAEncryption")) return SIG_ALGO_RSA_SHA256;
165 if (!strcmp(alg, "dsa_with_SHA256")) return SIG_ALGO_DSA_SHA256;
166 if (!strcmp(alg, "sha384WithRSAEncryption")) return SIG_ALGO_RSA_SHA384;
167 if (!strcmp(alg, "sha384WithDSAEncryption")) return SIG_ALGO;
168 if (!strcmp(alg, "sha512WithRSAEncryption")) return SIG_ALGO_RSA_SHA512;
169 return SIG_ALGO;
170 }
171
172 const char* zxid_get_cert_signature_algo_urlenc(X509* cert)
173 {
174 const char* alg = zxid_get_cert_signature_algo(cert);
175 if (!alg || !strcmp(alg, "")) return SIG_ALGO_URLENC;
176 if (!strcmp(alg, "sha1WithRSAEncryption")) return SIG_ALGO_RSA_SHA1_URLENC;
177 if (!strcmp(alg, "dsaWithSHA1")) return SIG_ALGO_DSA_SHA1_URLENC;
178 if (!strcmp(alg, "sha224WithRSAEncryption")) return SIG_ALGO_RSA_SHA224_URLENC;
179 if (!strcmp(alg, "sha224WithDSAEncryption")) return SIG_ALGO_URLENC;
180 if (!strcmp(alg, "sha256WithRSAEncryption")) return SIG_ALGO_RSA_SHA256_URLENC;
181 if (!strcmp(alg, "dsa_with_SHA256")) return SIG_ALGO_DSA_SHA256_URLENC;
182 if (!strcmp(alg, "sha384WithRSAEncryption")) return SIG_ALGO_RSA_SHA384_URLENC;
183 if (!strcmp(alg, "sha384WithDSAEncryption")) return SIG_ALGO_URLENC;
184 if (!strcmp(alg, "sha512WithRSAEncryption")) return SIG_ALGO_RSA_SHA512_URLENC;
185 return SIG_ALGO_URLENC;
186 }
187
188 const char* zxid_get_cert_digest_url(X509* cert)
189 {
190 const char* alg = zxid_get_cert_signature_algo(cert);
191 if (!alg || !strcmp(alg, "")) return DIGEST_ALGO;
192 if (!strcmp(alg, "sha1WithRSAEncryption")) return DIGEST_ALGO_SHA1;
193 if (!strcmp(alg, "sha224WithRSAEncryption")) return DIGEST_ALGO_SHA224;
194 if (!strcmp(alg, "sha256WithRSAEncryption")) return DIGEST_ALGO_SHA256;
195 if (!strcmp(alg, "sha384WithRSAEncryption")) return DIGEST_ALGO_SHA384;
196 if (!strcmp(alg, "sha512WithRSAEncryption")) return DIGEST_ALGO_SHA512;
197 return DIGEST_ALGO;
198 }
199 #endif
200
201 //static char*
202 #define priv_key_missing_msg "Private key missing. Perhaps you have not installed one in the certificate file in the /var/zxid/pem directory (or other directory if configured, see previous error messages for file reading trouble)? Other reasons: permissions do not allow reading the key (current uid=%d gid=%d), the directory permissions do not allow reading, the private key file is empty, wrong format, or corrupt; or the private key is protected with a password (remove password prior to use with zxid). Can also be caused by missing certificate. See http://zxid.org/html/zxid-cot.html for further help."
203
204 /*(i) Sign, using XML-DSIG, some XML data in the ~sref~ array. The XML data is canonicalized
205 * and the signature is generated and returned. Typically the caller will then insert the
206 * signature to the original data structure and canonicalize for transport.
207 *
208 * c:: ZX context. Used for memory allocation.
209 * n:: Number of elements in the sref array
210 * sref:: An array of <reference id, xml canon> tuples that are
211 * to be signed. See zxid_add_header_refs() for preparing sref array.
212 * cert:: Certificate (public key) used for signing
213 * priv_key:: Private key used for signing
214 * sig_meth_spec:: String used as SignatureMethod@Algorithm (i.e. a special URL
215 * like "http://www.w3.org/2000/09/xmldsig#rsa-sha1"). The public key part
216 * must agree with certificate. The hash part is used for choosing a hash
217 * algorithm. If specified as 0 or "0", the public key part is determined
218 * from the certificate and the hash part from the digest_spec. Since the
219 * mapping is nontrivial, not all combinations can be autodetected.
220 * This argument is usually fed from configuration option such as
221 * XMLDSIG_SIG_METH at a higher level.
222 * digest_spec:: String used as Reference/DigestMethod@Algorithm. The digest
223 * algorithm crypto level is determined by looking at suffix of this string. Special
224 * value 0 means to use same digest algorithm as used in the signing
225 * certificate. This argument is usually fed from configuration option such as
226 * XMLDSIG_DIGEST_ALGO at a higher level.
227 * return:: Signature as XML data, or 0 if failure.
228 *
229 * *Steps*
230 *
231 * 1. Canon tag(s) to sign (done by caller), pass as sig refs
232 * 2. Sha1 each sig ref
233 * 3. Construct the Signature element
234 * 4. Attach signature to the element (done by caller)
235 *
236 * *Typical XML-DSIG Signature*
237 *
238 * <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
239 * <ds:SignedInfo>
240 * <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
241 * <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
242 * <ds:Reference URI="#CREDm7unLxp2sOXQYfDR8E4F">
243 * <ds:Transforms>
244 * <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
245 * <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
246 * <ec:InclusiveNamespaces
247 * xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#"
248 * PrefixList="xasa"/></></>
249 * <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
250 * <ds:DigestValue>I2wmlQu11nvfSepvzor29kAZwAo=</></></>
251 * <ds:SignatureValue>
252 * FK6X9qO8qZntp3CeFbA7gpG9n9rWyJWlzSXy0vKNspwMGdl8HPfOGcXEs2Ts=</></>
253 */
254
255 /* Called by: zxid_anoint_a7n, zxid_anoint_sso_resp, zxid_az_soap x3, zxid_idp_soap_dispatch x2, zxid_idp_sso, zxid_mk_art_deref, zxid_sp_mni_soap, zxid_sp_slo_soap, zxid_sp_soap_dispatch x7, zxid_ssos_anreq, zxid_wsf_sign */
zxsig_sign(struct zx_ctx * c,int n,struct zxsig_ref * sref,X509 * cert,EVP_PKEY * priv_key,const char * sig_meth_spec,const char * digest_spec)256 struct zx_ds_Signature_s* zxsig_sign(struct zx_ctx* c, int n, struct zxsig_ref* sref, X509* cert, EVP_PKEY* priv_key, const char* sig_meth_spec, const char* digest_spec)
257 {
258 const EVP_MD* evp_sig_digest;
259 const EVP_MD* evp_digest;
260 unsigned char mdbuf[EVP_MAX_MD_SIZE];
261 int mdlen;
262 const char* dig_alg;
263 char* sigu;
264 int siglen;
265 RSA* rsa;
266 DSA* dsa;
267 EC_KEY* ec;
268 struct zx_str* ss;
269 struct zx_str* b64;
270 struct zx_ds_Reference_s* ref;
271 struct zx_ds_Signature_s* sig;
272 struct zx_ds_SignedInfo_s* si;
273
274 if (!priv_key || !cert) {
275 ERR(priv_key_missing_msg, geteuid(), getegid());
276 return 0;
277 }
278 #if 1
279 /* The digest_spec is typically passed from configuration option XMLDSIG_DIGEST_ALGO,
280 * which see for documentation. Typical value "http://www.w3.org/2000/09/xmldsig#sha1".
281 * Here we basically use fuzzy or heuristic detection in the hope that all the myriard
282 * algorithm URLs that are in use out there (some standards based, some not) will match. */
283 if (!digest_spec || (digest_spec[0]=='0'&&!digest_spec[1])) {
284 dig_alg = zxsig_extract_hash_algo(zxid_get_cert_signature_algo(cert), &digest_spec);
285 } else {
286 dig_alg = zxsig_extract_hash_algo(digest_spec, 0);
287 }
288 OpenSSL_add_all_digests();
289 evp_digest = EVP_get_digestbyname(dig_alg);
290 if (!evp_digest) {
291 ERR("digest algorithm(%s) not found or not supported at libcrypto (OpenSSL) level. digest_spec(%s)", dig_alg, digest_spec);
292 return 0;
293 }
294
295 if (!sig_meth_spec || (sig_meth_spec[0]=='0'&&!sig_meth_spec[1])) {
296 evp_sig_digest = evp_digest; /* sig_meth_spec not given, use same as digest_spec */
297 sig_meth_spec = zxsig_choose_xmldsig_sig_meth_url(priv_key, dig_alg);
298 } else {
299 dig_alg = zxsig_extract_hash_algo(sig_meth_spec, 0);
300 evp_sig_digest = EVP_get_digestbyname(dig_alg);
301 if (!evp_sig_digest) {
302 ERR("signature digest algorithm(%s) not found or not supported at libcrypto (OpenSSL) level. Signature method specification(%s)", dig_alg, sig_meth_spec);
303 return 0;
304 }
305 }
306 #else
307 memset(mdbuf, 0, sizeof(mdbuf));
308 const char* sig_alg = zxid_get_cert_signature_algo_url(cert);
309 si->SignatureMethod->Algorithm = zx_ref_attr(c, &si->SignatureMethod->gg, zx_Algorithm_ATTR, sig_alg);
310 //si->SignatureMethod->Algorithm = zx_ref_attr(c, &si->SignatureMethod->gg, zx_Algorithm_ATTR, SIG_ALGO);
311 #endif
312
313 sig = zx_NEW_ds_Signature(c,0);
314 si = sig->SignedInfo = zx_NEW_ds_SignedInfo(c, &sig->gg);
315 si->CanonicalizationMethod = zx_NEW_ds_CanonicalizationMethod(c, &si->gg);
316 si->CanonicalizationMethod->Algorithm = zx_ref_attr(c, &si->CanonicalizationMethod->gg, zx_Algorithm_ATTR, CANON_ALGO);
317 si->SignatureMethod = zx_NEW_ds_SignatureMethod(c, &si->gg);
318 si->SignatureMethod->Algorithm = zx_ref_attr(c, &si->SignatureMethod->gg, zx_Algorithm_ATTR, sig_meth_spec);
319
320 for (; n; --n, ++sref) {
321 ref = zx_NEW_ds_Reference(c, &si->gg);
322 ref->Transforms = zx_NEW_ds_Transforms(c, &ref->gg);
323 ref->Transforms->Transform = zx_NEW_ds_Transform(c, &ref->Transforms->gg);
324 ref->Transforms->Transform->Algorithm = zx_ref_attr(c, &ref->Transforms->Transform->gg, zx_Algorithm_ATTR, CANON_ALGO);
325
326 ref->Transforms->Transform = zx_NEW_ds_Transform(c, &ref->Transforms->gg);
327 ref->Transforms->Transform->Algorithm = zx_ref_attr(c, &ref->Transforms->Transform->gg, zx_Algorithm_ATTR, ENVELOPED_ALGO);
328
329 ref->URI = zx_attrf(c, &ref->gg, zx_URI_ATTR, "#%.*s", sref->id->len, sref->id->s);
330 ref->DigestMethod = zx_NEW_ds_DigestMethod(c, &ref->gg);
331
332 #if 1
333 //ref->DigestMethod->Algorithm = zx_ref_attr(c, &ref->DigestMethod->gg, zx_Algorithm_ATTR, DIGEST_ALGO);
334 //SHA1((unsigned char*)sref->canon->s, sref->canon->len, (unsigned char*)mdbuf);
335 //mdlen = 20
336 ref->DigestMethod->Algorithm = zx_ref_attr(c, &ref->DigestMethod->gg, zx_Algorithm_ATTR, digest_spec);
337 mdlen = zx_raw_raw_digest2(c, (char*)mdbuf, evp_digest, sref->canon->len, sref->canon->s, 0,0);
338 #else
339 ref->DigestMethod->Algorithm = zx_ref_attr(c, &ref->DigestMethod->gg, zx_Algorithm_ATTR, zxid_get_cert_digest_url(cert));
340
341 if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA1)) {
342 SHA1((unsigned char*)sref->canon->s, sref->canon->len, (unsigned char*)mdbuf);
343 mdlen = 20;
344 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA224)) {
345 SHA224((unsigned char*)sref->canon->s, sref->canon->len, (unsigned char*)mdbuf);
346 mdlen = 28;
347 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA256)) {
348 SHA256((unsigned char*)sref->canon->s, sref->canon->len, (unsigned char*)mdbuf);
349 mdlen = 32;
350 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA384)) {
351 SHA384((unsigned char*)sref->canon->s, sref->canon->len, (unsigned char*)mdbuf);
352 mdlen = 48;
353 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA512)) {
354 SHA512((unsigned char*)sref->canon->s, sref->canon->len, (unsigned char*)mdbuf);
355 mdlen = 64;
356 } else {
357 SHA1((unsigned char*)sref->canon->s, sref->canon->len, (unsigned char*)mdbuf);
358 mdlen = 20;
359 }
360 #endif
361 b64 = zx_new_len_str(c, SIMPLE_BASE64_LEN(mdlen));
362 base64_fancy_raw((char*)mdbuf, mdlen, b64->s, std_basis_64, 1<<31, 0, 0, '=');
363 ref->DigestValue = zx_new_str_elem(c, &ref->gg, zx_ds_DigestValue_ELEM, b64);
364 si->Reference = ref; /* *** Need to reverse the list? */
365 /* This debug print allows you to debug canonicalization related signature
366 * problems from the signer's end. The verifier's end is around line zxsig.c:270
367 * in zxsig_validate() */
368 DD("SIG REF(#%.*s) hash(%.*s) CANON(%.*s)", sref->id->len, sref->id->s, b64->len, b64->s, sref->canon->len, sref->canon->s);
369 D("SIG REF(#%.*s) hash(%.*s)", sref->id->len, sref->id->s, b64->len, b64->s);
370 D_XML_BLOB(0, "SIG CANON", sref->canon->len, sref->canon->s);
371 zx_reverse_elem_lists(&si->Reference->gg);
372 }
373 zx_reverse_elem_lists(&si->gg);
374
375 /* Compute final hash over SignedInfo (which already contains hashes over referenced elements) */
376 c->enc_tail_opt = 0;
377 ss = zx_EASY_ENC_elem(c, &si->gg);
378 #if 1
379 //SHA1((unsigned char*)ss->s, ss->len, (unsigned char*)mdbuf);
380 mdlen = zx_raw_raw_digest2(c, (char*)mdbuf, evp_sig_digest, ss->len, ss->s, 0,0);
381 #else
382 if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA1)) SHA1((unsigned char*)ss->s, ss->len, (unsigned char*)mdbuf);
383 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA224)) SHA224((unsigned char*)ss->s, ss->len, (unsigned char*)mdbuf);
384 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA256)) SHA256((unsigned char*)ss->s, ss->len, (unsigned char*)mdbuf);
385 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA384)) SHA384((unsigned char*)ss->s, ss->len, (unsigned char*)mdbuf);
386 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA512)) SHA512((unsigned char*)ss->s, ss->len, (unsigned char*)mdbuf);
387 else SHA1((unsigned char*)ss->s, ss->len, (unsigned char*)mdbuf);
388 #endif
389 zx_str_free(c, ss);
390
391 /* *** Following section should be rewritten to use EVP API, e.g. SVP_SignInit_ex(),
392 * EVP_SignUpdate(), and EVP_SignFinal(). However the present lower level
393 * formulation makes it easier to debug broken signatures. */
394 switch (EVP_PKEY_type(priv_key->type)) {
395 case EVP_PKEY_RSA:
396 rsa = EVP_PKEY_get1_RSA(priv_key);
397 siglen = RSA_size(rsa);
398 sigu = ZX_ALLOC(c, siglen);
399
400 #if 1
401 //if (!RSA_sign(NID_sha1, (unsigned char*)mdbuf, sizeof(mdbuf), (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
402 if (!RSA_sign(EVP_MD_type(evp_sig_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
403 #else
404 if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA1)) {
405 if (!RSA_sign(NID_sha1, (unsigned char*)mdbuf, 20, (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
406 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA224)) {
407 if (!RSA_sign(NID_sha224, (unsigned char*)mdbuf, 28, (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
408 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA256)) {
409 if (!RSA_sign(NID_sha256, (unsigned char*)mdbuf, 32, (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
410 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA384)) {
411 if (!RSA_sign(NID_sha384, (unsigned char*)mdbuf, 48, (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
412 } else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA512)) {
413 if (!RSA_sign(NID_sha512, (unsigned char*)mdbuf, 64, (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
414 } else {
415 if (!RSA_sign(NID_sha1, (unsigned char*)mdbuf, 20, (unsigned char*)sigu, (unsigned int*)&siglen, rsa)) goto rsaerr;
416 }
417 #endif
418 break;
419
420 case EVP_PKEY_DSA:
421 dsa = EVP_PKEY_get1_DSA(priv_key);
422 siglen = DSA_size(dsa);
423 sigu = ZX_ALLOC(c, siglen);
424
425 #if 1
426 //if (!DSA_sign(NID_sha1, (unsigned char*)mdbuf, sizeof(mdbuf), (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
427 if (!DSA_sign(EVP_MD_type(evp_sig_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
428 #else
429 if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA1)) {
430 if (!DSA_sign(NID_sha1, (unsigned char*)mdbuf, 20, (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
431 } else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA224)) {
432 if (!DSA_sign(NID_sha224, (unsigned char*)mdbuf, 28, (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
433 } else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA256)) {
434 if (!DSA_sign(NID_sha256, (unsigned char*)mdbuf, 32, (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
435 } else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA384)) {
436 if (!DSA_sign(NID_sha384, (unsigned char*)mdbuf, 48, (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
437 } else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA512)) {
438 if (!DSA_sign(NID_sha512, (unsigned char*)mdbuf, 64, (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
439 } else {
440 if (!DSA_sign(NID_sha1, (unsigned char*)mdbuf, 20, (unsigned char*)sigu, (unsigned int*)&siglen, dsa)) goto dsaerr;
441 }
442 #endif
443 break;
444
445 case EVP_PKEY_EC:
446 ec = EVP_PKEY_get1_EC_KEY(priv_key);
447 siglen = ECDSA_size(ec);
448 sigu = ZX_ALLOC(c, siglen);
449 if (!ECDSA_sign(EVP_MD_type(evp_sig_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)sigu, (unsigned int*)&siglen, ec)) goto ecerr;
450 break;
451
452 #if 0
453 case EVP_PKEY_DH:
454 DH* dh = EVP_PKEY_get1_DH(priv_key);
455 siglen = DH_size(dh);
456 sigu = ZX_ALLOC(c, siglen);
457 if (!DH_sign(EVP_MD_type(evp_sig_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)sigu, (unsigned int*)&siglen, dh)) goto ecerr;
458 break;
459 #endif
460 default:
461 ERR("Unknown private key type 0x%x. Wrong or corrupt private key?", priv_key->type);
462 return 0;
463 }
464
465 b64 = zx_new_len_str(c, SIMPLE_BASE64_LEN(siglen));
466 base64_fancy_raw(sigu, siglen, b64->s, std_basis_64, 1<<31, 0, 0, '=');
467 ZX_FREE(c, sigu);
468 sig->SignatureValue = zx_NEW_ds_SignatureValue(c, &sig->gg);
469 zx_add_content(c, &sig->SignatureValue->gg, b64);
470 zx_reverse_elem_lists(&sig->gg);
471 return sig;
472 rsaerr:
473 ERR("RSA_sign() failed. Bad certificate or private key? %p", rsa);
474 zx_report_openssl_err("signing error");
475 ZX_FREE(c, sigu);
476 return 0;
477 dsaerr:
478 ERR("DSA_sign() failed. Bad certificate or private key? %p", dsa);
479 zx_report_openssl_err("signing error");
480 ZX_FREE(c, sigu);
481 return 0;
482 ecerr:
483 ERR("EC_sign() failed. Bad certificate or private key? %p", ec);
484 zx_report_openssl_err("signing error");
485 ZX_FREE(c, sigu);
486 return 0;
487 #if 0
488 dherr:
489 ERR("DH_sign() failed. Bad certificate or private key? %p", dh);
490 zx_report_openssl_err("signing error");
491 ZX_FREE(c, sigu);
492 return 0;
493 #endif
494 }
495
496 /*() CRNL->NL canonicalization is specified in xml-c14n */
497
498 /* Called by: zxsig_validate x2 */
zxsig_canon_crnl_inplace(struct zx_str * ss)499 static void zxsig_canon_crnl_inplace(struct zx_str* ss)
500 {
501 char* p;
502 char* lim;
503 if (!ss || !ss->len || !ss->s) {
504 ERR("Asked to canonicalize null or empty string %p", ss);
505 return;
506 }
507 p = ss->s;
508 lim = p + ss->len;
509 while (p < lim) {
510 p = memchr(p, 0x0d, lim-p);
511 if (!p)
512 break;
513 --lim;
514 D("Canonicalizing CRNL to NL %d", ((int)(lim-p)));
515 memmove(p, p+1, lim-p); /* *** could be more efficient */
516 }
517 ss->len = lim - ss->s;
518 }
519
520 /*(i) Validate XML-DSIG signature over XML data found in ~sref~ array.
521 * Signature is validated agaist provided certificate, which
522 * must have been previously looked up, usually using Issuer field of message
523 * and metadata of the signing party. Trust in the certificate must have
524 * been established by other means such as only populating trusted metadata.
525 *
526 * c:: ZX context. Used for memory allocation.
527 * cert:: Signing party's certificate (public key), typically from metadata. If NULL,
528 * then only the hashes (and hence canonicalization) are checked, but the
529 * public key crypto part is not performed, and ZXSIG_BAD_CERT is returned.
530 * sig:: Parsed XML-DSIG data structure
531 * n:: Number of elements in the sref array
532 * sref:: An array of <reference sref, xml data structure blob> tuples that are
533 * referenced by the signature
534 * return:: ZXSIG value. 0 (ZXSIG_OK) means success. Any other value is some sort of failure */
535
536 /* Called by: main x5, sig_validate x2, wsse_sec_validate, zxid_chk_sig, zxid_sp_sso_finalize, zxid_wsc_valid_re_env, zxid_wsf_validate_a7n, zxid_wsp_validate_env */
zxsig_validate(struct zx_ctx * c,X509 * cert,struct zx_ds_Signature_s * sig,int n,struct zxsig_ref * sref)537 int zxsig_validate(struct zx_ctx* c, X509* cert, struct zx_ds_Signature_s* sig, int n, struct zxsig_ref* sref)
538 {
539 EVP_PKEY* evp_pkey;
540 struct rsa_st* rsa_pkey;
541 struct dsa_st* dsa_pkey;
542 struct ec_key_st* ec_pkey;
543 int siz, verdict, nn;
544 char* old_sig_raw;
545 char* lim;
546 char* p;
547 char* q;
548 char md_calc[64]; /* SHA1 is 160 bits, SHA256 is 32 bytes, SHA512 is 64 bytes. */
549 char md_given[64]; /* SHA1 is 160 bits, SHA256 is 32 bytes, SHA512 is 64 bytes. */
550 struct zx_ns_s* ns;
551 struct zx_str* ss;
552 struct zx_str* dv;
553 struct zxsig_ref* ssref;
554 struct zx_ds_Transform_s* xform;
555 struct zx_str* algo;
556 c->exclude_sig = sig;
557
558 memset(md_calc, 0, sizeof(md_calc));
559 memset(md_given, 0, sizeof(md_given));
560 D("cert sigAlg=%s", zxid_get_cert_signature_algo(cert));
561
562 /* Figure out inclusive namespaces, if any. */
563 c->inc_ns = 0;
564 if (c->canon_inopt & ZXID_CANON_INOPT_SHIB215IDP_INCLUSIVENAMESPACES) {
565 INFO("Warning: Processing <InclusiveNamespaces> has been disabled (config option CANON_INOPT=1). The canonicalization may not be fully xml-exc-c14n compatible (but it may enable interoperation with an IdP that is not fully compatible). %x", c->canon_inopt);
566 } else {
567 for (ssref = sref, nn = n; nn; --nn, ++ssref) {
568 if (!ssref->sref->Transforms)
569 continue;
570 for (xform = ssref->sref->Transforms->Transform;
571 xform;
572 xform = (void*)xform->gg.g.n) {
573 if (xform->gg.g.tok != zx_ds_Transform_ELEM)
574 continue;
575 ss = xform->InclusiveNamespaces ? &xform->InclusiveNamespaces->PrefixList->g : 0;
576 if (!ss || !ss->len)
577 continue;
578 for (p = ss->s, lim = p + ss->len; p < lim; ) {
579 q = memchr(p, ' ', lim-p);
580 if (!q)
581 siz = lim-p;
582 else
583 siz = q - p;
584 ns = zx_prefix_seen(c, siz, p);
585 if (!ns) {
586 INFO("InclusiveNamespaces/@PrefixList contains unknown ns prefix(%.*s)", siz, p);
587 p += siz + 1;
588 continue;
589 }
590 p += siz + 1;
591 if (!zx_in_inc_ns(c, ns)) {
592 ns->inc_n = c->inc_ns;
593 c->inc_ns = ns;
594 }
595 }
596 }
597 }
598 }
599 c->inc_ns_len = c->inc_ns;
600 zx_pop_seen(sref->pop_seen);
601
602 algo = &sref->sref->DigestMethod->Algorithm->g;
603 for (; n; --n, ++sref) {
604 c->enc_tail_opt = 0;
605 ss = zx_EASY_ENC_elem(c, sref->blob);
606 zxsig_canon_crnl_inplace(ss);
607 if ( ZX_STR_ENDS_IN_CONST(algo, "#sha1")) {
608 SHA1((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
609 siz = 20;
610 } else if (ZX_STR_ENDS_IN_CONST(algo, "#sha224")) {
611 SHA224((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
612 siz = 28;
613 } else if (ZX_STR_ENDS_IN_CONST(algo, "#sha256")) {
614 SHA256((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
615 siz = 32;
616 } else if (ZX_STR_ENDS_IN_CONST(algo, "#sha384")) {
617 SHA384((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
618 siz = 48;
619 } else if (ZX_STR_ENDS_IN_CONST(algo, "#sha512")) {
620 SHA512((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
621 siz = 64;
622 } else if (ZX_STR_ENDS_IN_CONST(algo, "#md5")) {
623 MD5((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
624 siz = 16;
625 } else {
626 ERR("Unknown digest algo(%.*s) in sref(%.*s). Only SHA1, SHA224, SHA256, SHA384, SHA512 and MD5 are supported.",
627 algo->len, algo->s, sref->sref->URI->g.len, sref->sref->URI->g.s);
628 ZX_FREE(c, ss);
629 return ZXSIG_BAD_DALGO;
630 }
631 dv = ZX_GET_CONTENT(sref->sref->DigestValue);
632 if (dv->len != SIMPLE_BASE64_LEN(siz)) {
633 ERR("Message digest(%.*s) length incorrect (%d vs. %d) at sref(%.*s)",
634 dv->len, dv->s, dv->len, SIMPLE_BASE64_LEN(siz),
635 sref->sref->URI->g.len, sref->sref->URI->g.s);
636 ZX_FREE(c, ss);
637 return ZXSIG_DIGEST_LEN;
638 }
639 unbase64_raw(dv->s, dv->s + dv->len, md_given, zx_std_index_64);
640 if (memcmp(md_calc, md_given, siz)) {
641 /* See also debug print of original canonicalization for signature
642 * generation around line zxsig.c:115 in zxsig_sign() */
643 DD("Message digest(%.*s) mismatch at sref(%.*s), canon blob(%.*s)", dv->len, dv->s, sref->sref->URI->g.len, sref->sref->URI->g.s, ss->len, ss->s);
644 ERR("Message digest(%.*s) mismatch at sref(%.*s)", dv->len, dv->s, sref->sref->URI->g.len, sref->sref->URI->g.s);
645 D_XML_BLOB(0, "VFY FAIL CANON BLOB", ss->len, ss->s);
646 ZX_FREE(c, ss);
647 return ZXSIG_BAD_DIGEST;
648 }
649 ZX_FREE(c, ss);
650 }
651 if (!cert) {
652 ERR("No certificate supplied. Only hashes (and hence canonicalization) verified. %d",0);
653 return ZXSIG_BAD_CERT;
654 }
655 c->exclude_sig = 0;
656 c->enc_tail_opt = 0;
657 ss = zx_EASY_ENC_elem(c, &sig->SignedInfo->gg);
658 zxsig_canon_crnl_inplace(ss);
659 algo = &sig->SignedInfo->SignatureMethod->Algorithm->g;
660 evp_pkey = X509_get_pubkey(cert);
661 if (!evp_pkey) goto certerr;
662
663 dv = ZX_GET_CONTENT(sig->SignatureValue);
664 old_sig_raw = ZX_ALLOC(c, SIMPLE_BASE64_PESSIMISTIC_DECODE_LEN(dv->len));
665 lim = unbase64_raw(dv->s, dv->s + dv->len, old_sig_raw, zx_std_index_64);
666 if ( ZX_STR_ENDS_IN_CONST(algo, "#rsa-sha1")) {
667 /* PKCS#1 v2.0 */
668 rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey);
669 if (!rsa_pkey) goto certerr;
670 SHA1((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
671 DD("VFY rsa-sha1 (PKCS#1 v2.0) canon sigInfo(%.*s) %d", ss->len, ss->s, hexdmp("inner sha1: ", md_calc,20,20));
672 verdict = RSA_verify(NID_sha1, (unsigned char*)md_calc, 20, (unsigned char*)old_sig_raw, lim - old_sig_raw, rsa_pkey);
673 if (!verdict) goto vfyerr;
674 } else if (ZX_STR_ENDS_IN_CONST(algo, "#dsa-sha1")) {
675 dsa_pkey = EVP_PKEY_get1_DSA(evp_pkey);
676 if (!dsa_pkey) goto certerr;
677 SHA1((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
678 DD("VFY dsa-sha1 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha1: ",md_calc,20,20));
679 verdict = DSA_verify(NID_sha1, (unsigned char*)md_calc, 20, (unsigned char*)old_sig_raw, lim - old_sig_raw, dsa_pkey);
680 if (!verdict) goto vfyerr;
681 } else if (ZX_STR_ENDS_IN_CONST(algo, "#ecdsa-sha1")) {
682 ec_pkey = EVP_PKEY_get1_EC_KEY(evp_pkey);
683 if (!ec_pkey) goto certerr;
684 SHA1((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
685 DD("VFY ecdsa-sha1 canon sigInfo(%.*s) %d", ss->len,ss->s,hexdmp("inner sha1: ",md_calc,20,20));
686 verdict = ECDSA_verify(NID_sha1, (unsigned char*)md_calc, 20, (unsigned char*)old_sig_raw, lim - old_sig_raw, ec_pkey);
687 if (!verdict) goto vfyerr;
688
689 } else if (ZX_STR_ENDS_IN_CONST(algo, "#rsa-sha224")) {
690 rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey);
691 if (!rsa_pkey) goto certerr;
692 SHA224((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
693 DD("VFY rsa-sha224 canon sigInfo(%.*s) %d", ss->len, ss->s, hexdmp("inner sha224: ",md_calc,28,28));
694 verdict = RSA_verify(NID_sha224, (unsigned char*)md_calc, 28, (unsigned char*)old_sig_raw, lim - old_sig_raw, rsa_pkey);
695 if (!verdict) goto vfyerr;
696 } else if (ZX_STR_ENDS_IN_CONST(algo, "#dsa-sha224")) {
697 dsa_pkey = EVP_PKEY_get1_DSA(evp_pkey);
698 if (!dsa_pkey) goto certerr;
699 SHA224((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
700 DD("VFY dsa-sha256 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha224: ",md_calc,28,28));
701 verdict = DSA_verify(NID_sha224, (unsigned char*)md_calc, 28, (unsigned char*)old_sig_raw, lim - old_sig_raw, dsa_pkey);
702 if (!verdict) goto vfyerr;
703 } else if (ZX_STR_ENDS_IN_CONST(algo, "#ecdsa-sha224")) {
704 ec_pkey = EVP_PKEY_get1_EC_KEY(evp_pkey);
705 if (!ec_pkey) goto certerr;
706 SHA224((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
707 DD("VFY ecdsa-sha256 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha224: ",md_calc,28,28));
708 verdict = ECDSA_verify(NID_sha224, (unsigned char*)md_calc, 28, (unsigned char*)old_sig_raw, lim - old_sig_raw, ec_pkey);
709 if (!verdict) goto vfyerr;
710
711 } else if (ZX_STR_ENDS_IN_CONST(algo, "#rsa-sha256")) {
712 rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey);
713 if (!rsa_pkey) goto certerr;
714 SHA256((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
715 DD("VFY rsa-sha256 canon sigInfo(%.*s) %d", ss->len, ss->s, hexdmp("inner sha256: ",md_calc,32,32));
716 verdict = RSA_verify(NID_sha256, (unsigned char*)md_calc, 32, (unsigned char*)old_sig_raw, lim - old_sig_raw, rsa_pkey);
717 if (!verdict) goto vfyerr;
718 } else if (ZX_STR_ENDS_IN_CONST(algo, "#dsa-sha256")) {
719 dsa_pkey = EVP_PKEY_get1_DSA(evp_pkey);
720 if (!dsa_pkey) goto certerr;
721 SHA256((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
722 DD("VFY dsa-sha256 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha256: ",md_calc,32,32));
723 verdict = DSA_verify(NID_sha256, (unsigned char*)md_calc, 32, (unsigned char*)old_sig_raw, lim - old_sig_raw, dsa_pkey);
724 if (!verdict) goto vfyerr;
725 } else if (ZX_STR_ENDS_IN_CONST(algo, "#ecdsa-sha256")) {
726 ec_pkey = EVP_PKEY_get1_EC_KEY(evp_pkey);
727 if (!ec_pkey) goto certerr;
728 SHA256((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
729 DD("VFY ecdsa-sha256 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha256: ",md_calc,32,32));
730 verdict = ECDSA_verify(NID_sha256, (unsigned char*)md_calc, 32, (unsigned char*)old_sig_raw, lim - old_sig_raw, ec_pkey);
731 if (!verdict) goto vfyerr;
732
733 } else if (ZX_STR_ENDS_IN_CONST(algo, "#rsa-sha384")) {
734 rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey);
735 if (!rsa_pkey) goto certerr;
736 SHA384((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
737 DD("VFY rsa-sha384 canon sigInfo(%.*s) %d", ss->len, ss->s, hexdmp("inner sha384: ",md_calc,48,48));
738 verdict = RSA_verify(NID_sha384, (unsigned char*)md_calc, 48, (unsigned char*)old_sig_raw, lim - old_sig_raw, rsa_pkey);
739 if (!verdict) goto vfyerr;
740 } else if (ZX_STR_ENDS_IN_CONST(algo, "#dsa-sha384")) {
741 dsa_pkey = EVP_PKEY_get1_DSA(evp_pkey);
742 if (!dsa_pkey) goto certerr;
743 SHA384((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
744 DD("VFY dsa-sha384 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha384: ",md_calc,48,48));
745 verdict = DSA_verify(NID_sha384, (unsigned char*)md_calc, 48, (unsigned char*)old_sig_raw, lim - old_sig_raw, dsa_pkey);
746 if (!verdict) goto vfyerr;
747 } else if (ZX_STR_ENDS_IN_CONST(algo, "#ecdsa-sha384")) {
748 ec_pkey = EVP_PKEY_get1_EC_KEY(evp_pkey);
749 if (!ec_pkey) goto certerr;
750 SHA384((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
751 DD("VFY ecdsa-sha384 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha384: ",md_calc,48,48));
752 verdict = ECDSA_verify(NID_sha384, (unsigned char*)md_calc, 48, (unsigned char*)old_sig_raw, lim - old_sig_raw, ec_pkey);
753 if (!verdict) goto vfyerr;
754
755 } else if (ZX_STR_ENDS_IN_CONST(algo, "#rsa-sha512")) {
756 rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey);
757 if (!rsa_pkey) goto certerr;
758 SHA512((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
759 DD("VFY rsa-sha512 canon sigInfo(%.*s) %d", ss->len, ss->s, hexdmp("inner sha512: ",md_calc,64,64));
760 verdict = RSA_verify(NID_sha512, (unsigned char*)md_calc, 64, (unsigned char*)old_sig_raw, lim - old_sig_raw, rsa_pkey);
761 if (!verdict) goto vfyerr;
762 } else if (ZX_STR_ENDS_IN_CONST(algo, "#dsa-sha512")) {
763 dsa_pkey = EVP_PKEY_get1_DSA(evp_pkey);
764 if (!dsa_pkey) goto certerr;
765 SHA512((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
766 DD("VFY dsa-sha512 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha256: ",md_calc,64,64));
767 verdict = DSA_verify(NID_sha512, (unsigned char*)md_calc, 64, (unsigned char*)old_sig_raw, lim - old_sig_raw, dsa_pkey);
768 if (!verdict) goto vfyerr;
769 } else if (ZX_STR_ENDS_IN_CONST(algo, "#ecdsa-sha512")) {
770 ec_pkey = EVP_PKEY_get1_EC_KEY(evp_pkey);
771 if (!ec_pkey) goto certerr;
772 SHA512((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
773 DD("VFY ecdsa-sha512 canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner sha256: ",md_calc,64,64));
774 verdict = ECDSA_verify(NID_sha512, (unsigned char*)md_calc, 64, (unsigned char*)old_sig_raw, lim - old_sig_raw, ec_pkey);
775 if (!verdict) goto vfyerr;
776
777 } else if (ZX_STR_ENDS_IN_CONST(algo, "#rsa-md5")) {
778 rsa_pkey = EVP_PKEY_get1_RSA(evp_pkey);
779 if (!rsa_pkey) goto certerr;
780 MD5((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
781 DD("VFY rsa-md5 canon sigInfo(%.*s) %d", ss->len, ss->s, hexdmp("inner md5: ",md_calc,16,16));
782 verdict = RSA_verify(NID_md5, (unsigned char*)md_calc, 16, (unsigned char*)old_sig_raw, lim - old_sig_raw, rsa_pkey);
783 if (!verdict) goto vfyerr;
784 } else if (ZX_STR_ENDS_IN_CONST(algo, "#dsa-md5")) {
785 dsa_pkey = EVP_PKEY_get1_DSA(evp_pkey);
786 if (!dsa_pkey) goto certerr;
787 MD5((unsigned char*)ss->s, ss->len, (unsigned char*)md_calc);
788 DD("VFY dsa-md5 canon sigInfo(%.*s) %d", ss->len, ss->s, hexdmp("inner md5: ",md_calc,16,16));
789 verdict = DSA_verify(NID_md5, (unsigned char*)md_calc, 16, (unsigned char*)old_sig_raw, lim - old_sig_raw, dsa_pkey);
790 if (!verdict) goto vfyerr;
791 } else {
792 ERR("Unknown digest algo(%.*s) in sref(%.*s). Only SHA1, SHA224, SHA256, SHA384, SHA512, and MD5 are supported.",
793 sref->sref->DigestMethod->Algorithm->g.len, sref->sref->DigestMethod->Algorithm->g.s,
794 sref->sref->URI->g.len, sref->sref->URI->g.s);
795 ZX_FREE(c, ss);
796 return ZXSIG_BAD_SALGO;
797 }
798 ZX_FREE(c, ss);
799 return ZXSIG_OK;
800
801 certerr:
802 ERR("Certificate error. Maybe the certificate does not have any public key type=0x%x matching the algorithm(%.*s)? Or corrupt or wrong cert?", evp_pkey?evp_pkey->type:-1, algo?algo->len:0, algo?algo->s:"");
803 zx_report_openssl_err("certificate error");
804 ZX_FREE(c, ss);
805 return ZXSIG_BAD_CERT;
806
807 vfyerr:
808 zx_report_openssl_err("verification error");
809 DD("VFY FAIL canon sigInfo(%.*s) %d", ss->len, ss->s,hexdmp("inner md_calc: ", md_calc, 64, 64));
810 ERR("VFY FAIL canon sigInfo md %d", hexdmp("inner md_calc: ", md_calc, 64, 64));
811 D_XML_BLOB(0, "VFY FAIL CANON SIGINFO", ss->len, ss->s);
812 ZX_FREE(c, ss);
813 return ZXSIG_VFY_FAIL;
814 }
815
816 /*() Walk through the OpenSSL error stack and dump it to the stderr.
817 *
818 * logkey:: Way for caller to indicate what the OpenSSL errors are all about
819 * return:: Number of open SSL errors processed, or 0 if none. Often ignored. */
820
821 /* Called by: */
zx_report_openssl_err(const char * logkey)822 int zx_report_openssl_err(const char* logkey)
823 {
824 char buf[256];
825 unsigned long err;
826 const char* file;
827 const char* data;
828 int flags, line, n_err = 0;
829 buf[0] = 0;
830 while ((err = ERR_get_error_line_data((const char**)&file, &line, (const char**)&data, &flags))) {
831 ERR_error_string_n(err, buf, sizeof(buf));
832 buf[sizeof(buf)-1] = 0;
833 ERR("%s: OpenSSL error(%lu) %s (%s:%d): %s %x", logkey, err,
834 buf, STRNULLCHK(file), line,
835 (data && (flags & ERR_TXT_STRING)) ? data : "?", flags);
836 }
837 return n_err;
838 }
839
840 /* --------------- Raw data signing and verification. These are building blocks. -------------- */
841
842 /*() Sign a blob of data using rsa-sha* or dsa-sha* algorithm.
843 *
844 * c:: ZX context. Used for memory allocation.
845 * len:: Length of the raw data
846 * data:: Raw data to sign
847 * sig:: Result parameter. Raw binary signature data, which will
848 * be allocated, will be returned via this parameter.
849 * priv_key:: Private key used for signing.
850 * lk:: Log key. Used to make logs and error messages more meaningful.
851 * md_alg:: Message digest algorithm used for signature, such as "SHA1" or "SHA256"
852 * return:: -1 on failure. Upon success the length of the raw signature data. */
853
854 /* Called by: zxbus_mint_receipt, zxid_saml2_post_enc, zxid_saml2_redir_enc, zxlog_write_line x2 */
zxsig_data(struct zx_ctx * c,int len,const char * data,char ** sig,EVP_PKEY * priv_key,const char * lk,const char * md_alg)855 int zxsig_data(struct zx_ctx* c, int len, const char* data, char** sig, EVP_PKEY* priv_key, const char* lk, const char* md_alg)
856 {
857 RSA* rsa;
858 DSA* dsa;
859 //DH* dh;
860 EC_KEY* ec;
861 const EVP_MD* evp_digest;
862 int mdlen;
863 unsigned char mdbuf[EVP_MAX_MD_SIZE]; /* 160 bits for sha1, 64 bytes for sha512 */
864 memset(mdbuf, 0, sizeof(mdbuf));
865 #if 1
866 //SHA1((unsigned char*)data, len, mdbuf);
867 if (!md_alg || (md_alg[0]=='0'&&!md_alg[1]))
868 md_alg = "SHA1";
869 evp_digest = EVP_get_digestbyname(md_alg);
870 mdlen = zx_raw_raw_digest2(c, (char*)mdbuf, evp_digest, len, data, 0,0);
871 #else
872 if (!md_alg || !strcmp(md_alg, SIG_ALGO_RSA_SHA1))
873 SHA1((unsigned char*)data, len, mdbuf);
874 else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA224))
875 SHA224((unsigned char*)data, len, mdbuf);
876 else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA256))
877 SHA256((unsigned char*)data, len, mdbuf);
878 else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA384))
879 SHA384((unsigned char*)data, len, mdbuf);
880 else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA512))
881 SHA512((unsigned char*)data, len, mdbuf);
882 else {
883 ERR("%s: Unknown message digest algorithm specification (%s). Using SHA1 instead.", lk, md_alg);
884 return -1;
885 SHA1((unsigned char*)data, len, mdbuf);
886 }
887 #endif
888
889 D("%s: len=%d data(%.*s)", lk, len, len, data);
890 D("%s: data above %d", lk, hexdump("data: ", data, data+len, 4096));
891 D("%s: digest above %d", lk, hexdump("digest: ", mdbuf, mdbuf+mdlen, 64));
892
893 if (!priv_key) {
894 ERR(priv_key_missing_msg, geteuid(), getegid());
895 return 0;
896 }
897
898 switch (EVP_PKEY_type(priv_key->type)) {
899 case EVP_PKEY_RSA:
900 rsa = EVP_PKEY_get1_RSA(priv_key);
901 len = RSA_size(rsa);
902 *sig = ZX_ALLOC(c, len);
903 D("RSA mdalg(%s) nid=%d sha1_nid=%d mdlen=%d siglen=%d", STRNULLCHKD(md_alg), EVP_MD_type(evp_digest), NID_sha1, mdlen, len);
904 #if 1
905 //if (RSA_sign(NID_sha1, mdbuf, 20, (unsigned char*)*sig, (unsigned int*)&len, rsa)) /* PKCS#1 v2.0 */ return len;
906 if (RSA_sign(EVP_MD_type(evp_digest), mdbuf, mdlen, (unsigned char*)*sig, (unsigned int*)&len, rsa)) {
907 DD("data = %s, SHA1 sig = %s, siglen = %d", data, *sig, len);
908 D("RSA siglen = %d", len);
909 D("%s: sig above %d", lk, hexdump("sig: ", *sig, *sig+len, 1024));
910 return len;
911 }
912 #else
913 if (!md_alg || !strcmp(md_alg, SIG_ALGO_RSA_SHA1)) {
914 if (RSA_sign(NID_sha1, mdbuf, 20, (unsigned char*)*sig, (unsigned int*)&len, rsa)) /* PKCS#1 v2.0 */ {
915 D("data = %s, SHA1 sig = %s, siglen = %d", data, *sig, len);
916 return len;
917 }
918 } else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA224)) {
919 if (RSA_sign(NID_sha224, mdbuf, 28, (unsigned char*)*sig, (unsigned int*)&len, rsa)) /* PKCS#1 v2.0 */ {
920 D("data = %s, SHA224 sig = %s, siglen = %d", data, *sig, len);
921 return len;
922 }
923 } else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA256)) {
924 if (RSA_sign(NID_sha256, mdbuf, 32, (unsigned char*)*sig, (unsigned int*)&len, rsa)) /* PKCS#1 v2.0 */ {
925 D("data = %s, SHA256 sig = %s, siglen = %d", data, *sig, len);
926 return len;
927 }
928 } else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA384)) {
929 if (RSA_sign(NID_sha384, mdbuf, 48, (unsigned char*)*sig, (unsigned int*)&len, rsa)) /* PKCS#1 v2.0 */ {
930 D("data = %s, SHA384 sig = %s, siglen = %d", data, *sig, len);
931 return len;
932 }
933 } else if (!strcmp(md_alg, SIG_ALGO_RSA_SHA512)) {
934 if (RSA_sign(NID_sha512, mdbuf, 64, (unsigned char*)*sig, (unsigned int*)&len, rsa)) /* PKCS#1 v2.0 */ {
935 D("data = %s, SHA512 sig = %s, siglen = %d", data, *sig, len);
936 return len;
937 }
938 } else {
939 if (RSA_sign(NID_sha1, mdbuf, 20, (unsigned char*)*sig, (unsigned int*)&len, rsa)) /* PKCS#1 v2.0 */ {
940 D("data = %s, default SHA1 sig = %s, siglen = %d", data, *sig, len);
941 return len;
942 }
943 }
944 #endif
945 ERR("%s: signing data failed. Perhaps you have bad, or no, RSA private key(%p) len=%d data=%p", lk, rsa, len, data);
946 zx_report_openssl_err(lk);
947 return -1;
948
949 case EVP_PKEY_DSA:
950 dsa = EVP_PKEY_get1_DSA(priv_key);
951 len = DSA_size(dsa);
952 *sig = ZX_ALLOC(c, len);
953 #if 1
954 //if (DSA_sign(NID_sha1, mdbuf, 20, (unsigned char*)*sig, (unsigned int*)&len, dsa)) /* PKCS#1 v2.0 */ return len;
955 if (DSA_sign(EVP_MD_type(evp_digest), mdbuf, mdlen, (unsigned char*)*sig, (unsigned int*)&len, dsa))
956 return len;
957 #else
958 if (!md_alg || !strcmp(md_alg, SIG_ALGO_DSA_SHA1)) {
959 if (DSA_sign(NID_sha1, mdbuf, 20, (unsigned char*)*sig, (unsigned int*)&len, dsa)) /* PKCS#1 v2.0 */
960 return len;
961 } else if (!strcmp(md_alg, SIG_ALGO_DSA_SHA224)) {
962 if (DSA_sign(NID_sha224, mdbuf, 28, (unsigned char*)*sig, (unsigned int*)&len, dsa)) /* PKCS#1 v2.0 */
963 return len;
964 } else if (!strcmp(md_alg, SIG_ALGO_DSA_SHA256)) {
965 if (DSA_sign(NID_sha256, mdbuf, 32, (unsigned char*)*sig, (unsigned int*)&len, dsa)) /* PKCS#1 v2.0 */
966 return len;
967 } else if (!strcmp(md_alg, SIG_ALGO_DSA_SHA384)) {
968 if (DSA_sign(NID_sha384, mdbuf, 48, (unsigned char*)*sig, (unsigned int*)&len, dsa)) /* PKCS#1 v2.0 */
969 return len;
970 } else if (!strcmp(md_alg, SIG_ALGO_DSA_SHA512)) {
971 if (DSA_sign(NID_sha512, mdbuf, 64, (unsigned char*)*sig, (unsigned int*)&len, dsa)) /* PKCS#1 v2.0 */
972 return len;
973 } else {
974 if (DSA_sign(NID_sha1, mdbuf, 20, (unsigned char*)*sig, (unsigned int*)&len, dsa)) /* PKCS#1 v2.0 */
975 return len;
976 }
977 #endif
978 ERR("%s: signing data failed. Perhaps you have bad, or no, DSA private key(%p) len=%d data=%p", lk, dsa, len, data);
979 zx_report_openssl_err(lk);
980 return -1;
981
982 case EVP_PKEY_EC:
983 ec = EVP_PKEY_get1_EC_KEY(priv_key);
984 len = ECDSA_size(ec);
985 *sig = ZX_ALLOC(c, len);
986 if (!ECDSA_sign(EVP_MD_type(evp_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)*sig, (unsigned int*)&len, ec))
987 return len;
988 ERR("%s: signing data failed. Perhaps you have bad, or no, ECDSA private key(%p) len=%d data=%p", lk, ec, len, data);
989 zx_report_openssl_err(lk);
990 return -1;
991
992 #if 0
993 case EVP_PKEY_DH:
994 DH* dh = EVP_PKEY_get1_DH(priv_key);
995 siglen = DH_size(dh);
996 *sig = ZX_ALLOC(c, len);
997 if (!DH_sign(EVP_MD_type(evp_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)*sig, (unsigned int*)&len, dh))
998 return len;
999 ERR("%s: signing data failed. Perhaps you have bad, or no, DH private key(%p) len=%d data=%p", lk, dh, len, data);
1000 zx_report_openssl_err(lk);
1001 return -1;
1002 #endif
1003
1004 default:
1005 ERR("%s: Unknown private key type 0x%x. Wrong or corrupt private key?", lk, priv_key->type);
1006 return -1;
1007 }
1008 }
1009
1010 /*() Verify a signature over a blob of data using rsa-sha* or dsa-sha* algorithm.
1011 *
1012 * len:: Length of the raw data
1013 * data:: Raw data that was signed
1014 * siglen:: Length of the raw binary signature data
1015 * sig:: Raw binary signature data
1016 * cert:: Certificate used for signing
1017 * lk:: Log key. Used to make logs and error messages more meaningful
1018 * mdalg:: Signature hashing algorithm, detected at higher level
1019 * return:: ZXSIG value. 0 (ZXSIG_OK) means success. Other values mean failure of some sort. */
1020
1021 /* Called by: main, zxbus_verify_receipt, zxid_decode_redir_or_post, zxlog_zsig_verify_print */
zxsig_verify_data(int len,char * data,int siglen,char * sig,X509 * cert,const char * lk,const char * mdalg)1022 int zxsig_verify_data(int len, char* data, int siglen, char* sig, X509* cert, const char* lk, const char* mdalg)
1023 {
1024 int verdict;
1025 const EVP_MD* evp_digest;
1026 EVP_PKEY* evp_pubk;
1027 struct rsa_st* rsa_pubk;
1028 struct dsa_st* dsa_pubk;
1029 char mdbuf[EVP_MAX_MD_SIZE]; /* 160 bits for sha1, 64 bytes for sha512 */
1030 int mdlen;
1031 #if 1
1032 //SHA1((unsigned char*)data, len, mdbuf);
1033 //const char* sig_alg = zxid_get_cert_signature_algo_url(cert);
1034 evp_digest = EVP_get_digestbyname(mdalg);
1035 mdlen = zx_raw_raw_digest2(0, mdbuf, evp_digest, len, data, 0,0);
1036 #else
1037 memset(mdbuf, 0, EVP_MAX_MD_SIZE);
1038 if (!strcmp(mdalg, "SHA1")) { SHA1((unsigned char*)data, len, mdbuf); nid = NID_sha1; }
1039 else if (!strcmp(mdalg, "SHA224")) { SHA224((unsigned char*)data, len, mdbuf); nid = NID_sha224; }
1040 else if (!strcmp(mdalg, "SHA256")) { SHA256((unsigned char*)data, len, mdbuf); nid = NID_sha256; }
1041 else if (!strcmp(mdalg, "SHA384")) { SHA384((unsigned char*)data, len, mdbuf); nid = NID_sha384; }
1042 else if (!strcmp(mdalg, "SHA512")) { SHA512((unsigned char*)data, len, mdbuf); nid = NID_sha512; }
1043 else { SHA1((unsigned char*)data, len, mdbuf); nid = NID_sha1; }
1044 #endif
1045 D("%s: vfy data len=%d above %d", lk, len, hexdump("data: ", data, data+len, 8192));
1046 D("%s: vfy sig above %d", lk, hexdump("sig: ", sig, sig+siglen, 8192));
1047 D("%s: vfy md above %d", lk, hexdump("md: ", mdbuf, mdbuf+64, 64));
1048
1049 evp_pubk = X509_get_pubkey(cert);
1050 if (!evp_pubk) {
1051 ERR("%s: Verify failed to get public key from certificate (perhaps you have not supplied any certificate, or it is corrupt or of wrong type) %p", lk, cert);
1052 zx_report_openssl_err("zxsig rsa vfy get_pub");
1053 return ZXSIG_BAD_CERT;
1054 }
1055 switch (EVP_PKEY_type(evp_pubk->type)) {
1056 case EVP_PKEY_RSA:
1057 rsa_pubk = EVP_PKEY_get1_RSA(evp_pubk);
1058 if (!rsa_pubk) {
1059 ERR("RSA vfy: failed to extract RSA get public key from certificate (perhaps you have not supplied any certificate, or it is corrupt or of wrong type) %p", cert);
1060 zx_report_openssl_err("zxsig rsa vfy rsa get_pub rsa");
1061 return ZXSIG_BAD_CERT;
1062 }
1063 D("RSA mdalg(%s) nid=%d sha1_nid=%d mdlen=%d siglen=%d", STRNULLCHKD(mdalg), EVP_MD_type(evp_digest), NID_sha1, mdlen, siglen);
1064 #if 1
1065 verdict = RSA_verify(EVP_MD_type(evp_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)sig, siglen, rsa_pubk);
1066 #else
1067 if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA1))
1068 verdict = RSA_verify(NID_sha1, mdbuf, 20, (unsigned char*)sig, siglen, rsa_pubk);
1069 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA224))
1070 verdict = RSA_verify(NID_sha224, mdbuf, 28, (unsigned char*)sig, siglen, rsa_pubk);
1071 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA256))
1072 verdict = RSA_verify(NID_sha256, mdbuf, 32, (unsigned char*)sig, siglen, rsa_pubk);
1073 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA384))
1074 verdict = RSA_verify(NID_sha384, mdbuf, 48, (unsigned char*)sig, siglen, rsa_pubk);
1075 else if (!strcmp(sig_alg, SIG_ALGO_RSA_SHA512))
1076 verdict = RSA_verify(NID_sha512, mdbuf, 64, (unsigned char*)sig, siglen, rsa_pubk);
1077 else
1078 verdict = RSA_verify(NID_sha1, mdbuf, 20, (unsigned char*)sig, siglen, rsa_pubk);
1079 #endif
1080 if (!verdict) {
1081 ERR("RSA signature verify in %s data failed. Perhaps you have bad or no certificate(%p) len=%d data=%p siglen=%d sig=%p", lk, cert, len, data, siglen, sig);
1082 zx_report_openssl_err(lk);
1083 D("RSA_vfy(%s) bad sig above %d", lk, hexdump("sig: ", sig, sig+siglen, 4096));
1084 return ZXSIG_VFY_FAIL;
1085 } else {
1086 D("RSA verify OK %d", verdict);
1087 return 0;
1088 }
1089
1090 case EVP_PKEY_DSA:
1091 dsa_pubk = EVP_PKEY_get1_DSA(evp_pubk);
1092 if (!dsa_pubk) {
1093 ERR("DSA vfy: failed to extract DSA get public key from certificate (perhaps you have not supplied any certificate, or it is corrupt or of wrong type) %p", cert);
1094 zx_report_openssl_err("zxsig dsa vfy dsa get_pub dsa");
1095 return ZXSIG_BAD_CERT;
1096 }
1097 D("DSA mdalg(%s) nid=%d sha1_nid=%d mdlen=%d siglen=%d", STRNULLCHKD(mdalg), EVP_MD_type(evp_digest), NID_sha1, mdlen, siglen);
1098 #if 1
1099 verdict = DSA_verify(EVP_MD_type(evp_digest), (unsigned char*)mdbuf, mdlen, (unsigned char*)sig, siglen, dsa_pubk);
1100 //verdict = DSA_verify(NID_sha1, mdbuf, 20, (unsigned char*)sig, siglen, dsa_pubk);
1101 #else
1102 if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA1))
1103 verdict = DSA_verify(NID_sha1, mdbuf, 20, (unsigned char*)sig, siglen, dsa_pubk);
1104 else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA224))
1105 verdict = DSA_verify(NID_sha224, mdbuf, 28, (unsigned char*)sig, siglen, dsa_pubk);
1106 else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA256))
1107 verdict = DSA_verify(NID_sha256, mdbuf, 32, (unsigned char*)sig, siglen, dsa_pubk);
1108 else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA384))
1109 verdict = DSA_verify(NID_sha384, mdbuf, 48, (unsigned char*)sig, siglen, dsa_pubk);
1110 else if (!strcmp(sig_alg, SIG_ALGO_DSA_SHA512))
1111 verdict = DSA_verify(NID_sha512, mdbuf, 64, (unsigned char*)sig, siglen, dsa_pubk);
1112 else
1113 verdict = DSA_verify(NID_sha1, mdbuf, 20, (unsigned char*)sig, siglen, dsa_pubk);
1114 #endif
1115 if (!verdict) {
1116 ERR("DSA signature verify in %s data failed. Perhaps you have bad or no certificate(%p) len=%d data=%p siglen=%d sig=%p", lk, cert, len, data, siglen, sig);
1117 zx_report_openssl_err(lk);
1118 D("DSA_vfy(%s) sig above %d", lk, hexdump("sig: ", sig, sig+siglen, 4096));
1119 return ZXSIG_VFY_FAIL;
1120 } else {
1121 D("DSA verify OK %d", verdict);
1122 return 0;
1123 }
1124 default:
1125 ERR("%s: Unknown public key type 0x%x. Wrong or corrupt certificate key?", lk, evp_pubk->type);
1126 return -1;
1127 }
1128 }
1129
1130 /* ------------- XML-ENC support -------------- */
1131
1132 // AES256-GCM-SHA384
1133 //#define AES256GCM "AES-256-GCM"
1134 #define AES256GCM "aes-256-gcm"
1135
1136 /*() Symmetric key decryption using XML-ENC. The encryption algorithm is
1137 * auto-detected from the XML-ENC data.
1138 *
1139 * cf:: ZXID configuration object, used for memory allocation
1140 * ed:: Encrypted data as XML data structure
1141 * symkey:: Symmetric key used for decryption
1142 * return:: Decrypted data as zx_str. Caller should free this memory. */
1143
1144 /* Called by: zxenc_privkey_dec */
zxenc_symkey_dec(zxid_conf * cf,struct zx_xenc_EncryptedData_s * ed,struct zx_str * symkey)1145 struct zx_str* zxenc_symkey_dec(zxid_conf* cf, struct zx_xenc_EncryptedData_s* ed, struct zx_str* symkey)
1146 {
1147 struct zx_str raw;
1148 struct zx_str* ss;
1149 char* lim;
1150
1151 if (!ed || !ed->CipherData || !(ss = ZX_GET_CONTENT(ed->CipherData->CipherValue))) {
1152 ERR("EncryptedData element not found or malformed %p", ed->CipherData);
1153 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "EMISS", 0, "no EncryptedData");
1154 return 0;
1155 }
1156
1157 if (!symkey || !symkey->s) {
1158 ERR("Symmetric key missing. Perhaps public key operation to recover symmetric key failed (e.g. missing private key, or private key does not match public key). Perhaps the programmer simply failed to pass correct arguments to this function. %p", symkey);
1159 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "EMISS", 0, "no symkey");
1160 return 0;
1161 }
1162
1163 raw.s = ZX_ALLOC(cf->ctx, SIMPLE_BASE64_PESSIMISTIC_DECODE_LEN(ss->len));
1164 lim = unbase64_raw(ss->s, ss->s+ss->len, raw.s, zx_std_index_64);
1165 raw.len = lim - raw.s;
1166
1167 if (!ed->EncryptionMethod || !ed->EncryptionMethod->Algorithm) {
1168 ERR("EncryptionMethod or Algorithm element not found or malformed %p", ed->EncryptionMethod);
1169 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "EMISS", 0, "no or bad EncryptionMethod");
1170 return 0;
1171 }
1172 ss = &ed->EncryptionMethod->Algorithm->g;
1173 if (sizeof(ENC_ALGO_TRIPLEDES_CBC)-1 == ss->len
1174 && !memcmp(ENC_ALGO_TRIPLEDES_CBC, ss->s, sizeof(ENC_ALGO_TRIPLEDES_CBC)-1)) {
1175 if (!(cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_ACCEPT)) goto backwards_compat_disa;
1176 if (symkey->len != (192 >> 3)) goto wrong_key_len;
1177 ss = zx_raw_cipher(cf->ctx, "DES-EDE3-CBC", 0, symkey, raw.len-8, raw.s+8, 8, raw.s);
1178
1179 } else if (sizeof(ENC_ALGO_AES128_CBC)-1 == ss->len
1180 && !memcmp(ENC_ALGO_AES128_CBC, ss->s, sizeof(ENC_ALGO_AES128_CBC)-1)) {
1181 if (!(cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_ACCEPT)) goto backwards_compat_disa;
1182 if (symkey->len != (128 >> 3)) goto wrong_key_len;
1183 ss = zx_raw_cipher(cf->ctx, "AES-128-CBC", 0, symkey, raw.len-16, raw.s+16, 16, raw.s);
1184
1185 } else if (sizeof(ENC_ALGO_AES192_CBC)-1 == ss->len
1186 && !memcmp(ENC_ALGO_AES192_CBC, ss->s, sizeof(ENC_ALGO_AES192_CBC)-1)) {
1187 if (!(cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_ACCEPT)) goto backwards_compat_disa;
1188 if (symkey->len != (192 >> 3)) goto wrong_key_len;
1189 ss = zx_raw_cipher(cf->ctx, "AES-192-CBC", 0, symkey, raw.len-16, raw.s+16, 16, raw.s);
1190
1191 } else if (sizeof(ENC_ALGO_AES256_CBC)-1 == ss->len
1192 && !memcmp(ENC_ALGO_AES256_CBC, ss->s, sizeof(ENC_ALGO_AES256_CBC)-1)) {
1193 if (!(cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_ACCEPT)) goto backwards_compat_disa;
1194 if (symkey->len != (256 >> 3)) goto wrong_key_len;
1195 ss = zx_raw_cipher(cf->ctx, "AES-256-CBC", 0, symkey, raw.len-16, raw.s+16, 16, raw.s);
1196 } else if (sizeof(ENC_ALGO_AES256_GCM)-1 == ss->len
1197 && !memcmp(ENC_ALGO_AES256_GCM, ss->s, sizeof(ENC_ALGO_AES256_GCM)-1)) {
1198 if (symkey->len != (256 >> 3)) goto wrong_key_len;
1199 ss = zx_raw_cipher(cf->ctx, AES256GCM, 0, symkey, raw.len-12, raw.s+12, 12, raw.s);
1200 } else {
1201 ERR("Unsupported key transformation method(%.*s)", ss->len, ss->s);
1202 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "ECRYPT", 0, "unsupported key transformation method");
1203 return 0;
1204 }
1205 if (!ss) {
1206 ERR("Symmetric key decryption failure. Perhaps symmetric key derived from assymmetric level is wrong, i.e. certificate used for encryption does not match the private key %d", 0);
1207 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "ECRYPT", 0, "symmetric decrypt failed");
1208 return 0;
1209 }
1210 ZX_FREE(cf->ctx, raw.s);
1211 DD("plain(%.*s)", ss->len, ss->s);
1212 D_XML_BLOB(cf, "PLAIN", ss->len, ss->s);
1213 return ss;
1214
1215 wrong_key_len:
1216 ZX_FREE(cf->ctx, raw.s);
1217 ERR("Wrong key length %d for algo(%.*s)", symkey->len, ss->len, ss->s);
1218 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "ECRYPT", 0, "wrong key length");
1219 return 0;
1220
1221 backwards_compat_disa:
1222 ERR("Backwards compatibility not enabled, old key transformation method(%.*s) blocked", ss->len, ss->s);
1223 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "EBC", 0, "backwards compatible method not enabled");
1224 return 0;
1225 }
1226
1227 /*() Private key decryption using XML-ENC. The encryption algorithm is
1228 * auto-detected from the XML-ENC data. The private key is looked up
1229 * from the configuration object.
1230 *
1231 * cf:: ZXID configuration object, used for memory allocation
1232 * ed:: Encrypted data as XML data structure
1233 * ek:: Symmetric encryption key data structure. If not supplied, the EncryptedKey
1234 * element from EncryptedData is used
1235 * return:: Decrypted data as zx_str. Caller should free this memory. */
1236
1237 /* Called by: zxid_dec_a7n, zxid_decrypt_nameid, zxid_decrypt_newnym, zxid_get_ses_sso_a7n */
zxenc_privkey_dec(zxid_conf * cf,struct zx_xenc_EncryptedData_s * ed,struct zx_xenc_EncryptedKey_s * ek)1238 struct zx_str* zxenc_privkey_dec(zxid_conf* cf, struct zx_xenc_EncryptedData_s* ed, struct zx_xenc_EncryptedKey_s* ek)
1239 {
1240 EVP_PKEY* enc_pkey;
1241 RSA* rsa;
1242 struct zx_str raw;
1243 struct zx_str* symkey;
1244 struct zx_str* ss;
1245 char* lim;
1246
1247 if (!ed) {
1248 ERR("Missing or malformed EncryptedData %d", 0);
1249 return 0;
1250 }
1251
1252 if (!ek && ed->KeyInfo)
1253 ek = ed->KeyInfo->EncryptedKey; /* Nested EncryptionKey method (Shib 2010) */
1254 if (!ek || !ek->CipherData || !(ss = ZX_GET_CONTENT(ek->CipherData->CipherValue)) || !ss->len) {
1255 ERR("EncryptedKey element not found or malformed %p", ek->CipherData);
1256 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "EMISS", 0, "EncryptedKey not found");
1257 return 0;
1258 }
1259
1260 raw.s = ZX_ALLOC(cf->ctx, SIMPLE_BASE64_PESSIMISTIC_DECODE_LEN(ss->len));
1261 lim = unbase64_raw(ss->s, ss->s+ss->len, raw.s, zx_std_index_64);
1262 raw.len = lim - raw.s;
1263
1264 LOCK(cf->mx, "zxenc_privkey_dec");
1265 if (!(enc_pkey = cf->enc_pkey))
1266 enc_pkey = cf->enc_pkey = zxid_read_private_key(cf, "enc-nopw-cert.pem");
1267 UNLOCK(cf->mx, "zxenc_privkey_dec");
1268 if (!enc_pkey)
1269 return 0;
1270
1271 if (!ek->EncryptionMethod || !(ss = &ek->EncryptionMethod->Algorithm->g) || !ss->len) {
1272 ERR("Missing or malformed EncryptionMethod %p", ek->EncryptionMethod);
1273 return 0;
1274 }
1275
1276 if (sizeof(ENC_KEYTRAN_RSA_1_5)-1 == ss->len
1277 && !memcmp(ENC_KEYTRAN_RSA_1_5, ss->s, sizeof(ENC_KEYTRAN_RSA_1_5)-1)) {
1278 if (!(cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_ACCEPT)) {
1279 ERR("PKCS#1 v1.5 disabled to prevent Backwards Compatibility Attacks (see http://www.nds.ruhr-uni-bochum.de/research/publications/backwards-compatibility/) %d",0);
1280 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "EBC", 0, "Ciphersuite rejected to prevent backwards compatibility attacks");
1281 return 0;
1282 }
1283 rsa = EVP_PKEY_get1_RSA(enc_pkey);
1284 symkey = zx_rsa_priv_dec(cf->ctx, &raw, rsa, RSA_PKCS1_PADDING);
1285 } else if (sizeof(ENC_KEYTRAN_RSA_OAEP)-1 == ss->len
1286 && !memcmp(ENC_KEYTRAN_RSA_OAEP, ss->s, sizeof(ENC_KEYTRAN_RSA_OAEP)-1)) {
1287 rsa = EVP_PKEY_get1_RSA(enc_pkey);
1288 symkey = zx_rsa_priv_dec(cf->ctx, &raw, rsa, RSA_PKCS1_OAEP_PADDING);
1289 } else {
1290 ERR("Unsupported key transformation method(%.*s)", ss->len, ss->s);
1291 zxlog(cf, 0, 0, 0, 0, 0, 0, 0, "N", "C", "ECRYPT", 0, "unsupported key transformation method");
1292 return 0;
1293 }
1294 ZX_FREE(cf->ctx, raw.s);
1295 if (symkey) {
1296 ss = zxenc_symkey_dec(cf, ed, symkey);
1297 zx_str_free(cf->ctx, symkey);
1298 return ss;
1299 } else
1300 return 0;
1301 }
1302
1303 /*() Symmetric key encryption using XML-ENC. The encryption algorith is
1304 * auto-detected from the XML-ENC data.
1305 *
1306 * cf:: ZXID configuration object, used for memory allocation
1307 * data:: Data blob to encrypt. Typically serialized XML
1308 * ed_id:: The value of the ~Id~ XML attribute of the <EncryptedData> element
1309 * symkey:: Raw symmetric key used for encryption
1310 * symkey_id:: The value of the ~Id~ XML attribute of the <EncryptedKey> element
1311 * return:: Encrypted data as XML data structure. Caller should free this memory.
1312 *
1313 * *Example of XML-ENC encrypted data using RetrievalMethod pointing to EncryptedID Id="EK38"*
1314 *
1315 * <sa:EncryptedID>
1316 * <e:EncryptedData
1317 * xmlns:e="http://www.w3.org/2001/04/xmlenc#"
1318 * Id="ED38"
1319 * Type="http://www.w3.org/2001/04/xmlenc#Element">
1320 * <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-gcm"/>
1321 * <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
1322 * <ds:RetrievalMethod
1323 * Type="http://www.w3.org/2001/04/xmlenc#EncryptedKey"
1324 * URI="#EK38"/></> # N.B. hash
1325 * <e:CipherData>
1326 * <e:CipherValue>FWfOV7aytBE2xIMe...YTA3ImLf9JCM/vdLIMizMf1</></></>
1327 *
1328 * <e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#" Id="EK38">
1329 * <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
1330 * <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
1331 * <ds:X509Data>
1332 * <ds:X509Certificate>***</></></>
1333 * <e:CipherData>
1334 * <e:CipherValue>xf5HkmQM68t...7zRbxkqtniIVnxBHjkA=</></>
1335 * <e:ReferenceList>
1336 * <e:DataReference URI="#ED38"/></></></> # N.B. hash
1337 *
1338 * Alternative formulation is to replace the EncryptedData/KeyInfo/RetrievalMethod
1339 * with EncryptedData/KeyInfo/EncryptedKey, i.e. inline the EncryptedKey. As of 2010
1340 * Shibboleth appears to support only this method.
1341 */
1342
1343 /* Called by: zxenc_pubkey_enc */
zxenc_symkey_enc(zxid_conf * cf,struct zx_str * data,struct zx_str * ed_id,struct zx_str * symkey,struct zx_xenc_EncryptedKey_s * ek)1344 struct zx_xenc_EncryptedData_s* zxenc_symkey_enc(zxid_conf* cf, struct zx_str* data, struct zx_str* ed_id, struct zx_str* symkey, struct zx_xenc_EncryptedKey_s* ek)
1345 {
1346 struct zx_str* ss;
1347 struct zx_str* b64;
1348 struct zx_xenc_EncryptedData_s* ed = zx_NEW_xenc_EncryptedData(cf->ctx,0);
1349 ed->Id = zx_ref_len_attr(cf->ctx, &ed->gg, zx_Id_ATTR, ed_id->len, ed_id->s);
1350 ed->Type = zx_ref_attr(cf->ctx, &ed->gg, zx_Type_ATTR, "http://www.w3.org/2001/04/xmlenc#Element");
1351 ed->EncryptionMethod = zx_NEW_xenc_EncryptionMethod(cf->ctx, &ed->gg);
1352 if (cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_GEN) {
1353 ed->EncryptionMethod->Algorithm = zx_ref_attr(cf->ctx, &ed->EncryptionMethod->gg, zx_Algorithm_ATTR, ENC_ALGO_AES128_CBC);
1354 } else {
1355 ed->EncryptionMethod->Algorithm = zx_ref_attr(cf->ctx, &ed->EncryptionMethod->gg, zx_Algorithm_ATTR, ENC_ALGO_AES256_GCM);
1356 }
1357 if (ek) {
1358 ed->KeyInfo = zx_NEW_ds_KeyInfo(cf->ctx, &ed->gg);
1359 if (cf->enckey_opt & 0x20) {
1360 D("Nested EncryptedKey %p", ek); /* Shibboleth early 2010 */
1361 ZX_ADD_KID(ed->KeyInfo, EncryptedKey, ek);
1362 } else {
1363 D("Sibling EncryptedKey with RetrievalMethod %p", ek);
1364 ed->KeyInfo->RetrievalMethod = zx_NEW_ds_RetrievalMethod(cf->ctx, &ed->KeyInfo->gg);
1365 ed->KeyInfo->RetrievalMethod->Type = zx_ref_attr(cf->ctx, &ed->KeyInfo->RetrievalMethod->gg, zx_Type_ATTR, "http://www.w3.org/2001/04/xmlenc#EncryptedKey");
1366 ed->KeyInfo->RetrievalMethod->URI = zx_attrf(cf->ctx, &ed->KeyInfo->RetrievalMethod->gg, zx_URI_ATTR, "#%.*s", ek->Id->g.len, ek->Id->g.s);
1367 }
1368 }
1369 DD("Plaintext(%.*s)", data->len, data->s);
1370 D_XML_BLOB(cf, "PLAINTEXT", data->len, data->s);
1371 if (cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_GEN) {
1372 /* CBC is no longer considered safe so do not use it. */
1373 ss = zx_raw_cipher(cf->ctx, "AES-128-CBC", 1, symkey, data->len, data->s, 16, 0);
1374 } else {
1375 ss = zx_raw_cipher(cf->ctx, AES256GCM, 1, symkey, data->len, data->s, 12, 0);
1376 }
1377 if (!ss) {
1378 ERR("Symmetric encryption failed %d",0);
1379 return 0;
1380 }
1381 b64 = zx_new_len_str(cf->ctx, SIMPLE_BASE64_LEN(ss->len));
1382 base64_fancy_raw(ss->s, ss->len, b64->s, std_basis_64, 0, 0, 0, '=');
1383 zx_str_free(cf->ctx, ss);
1384 ed->CipherData = zx_NEW_xenc_CipherData(cf->ctx, &ed->gg);
1385 ed->CipherData->CipherValue = zx_new_str_elem(cf->ctx, &ed->CipherData->gg, zx_xenc_CipherValue_ELEM, b64);
1386 zx_reverse_elem_lists(&ed->gg);
1387 return ed;
1388 }
1389
1390 /*() Public key encryption using XML-ENC. The encryption algorithm is
1391 * auto-detected from the XML-ENC data.
1392 *
1393 * cf:: ZXID configuration object, used for memory allocation
1394 * data:: Data blob to encrypt. Typically serialized XML
1395 * ekp:: Result parameter. XML data structure corresponding to the <EncryptedKey>
1396 * element will be returned. This is the encrypted symmetric key (which is
1397 * pseudorandom generated inside this function). Usually used to set EncryptedKey
1398 * field of EncryptedAssertion when using sister elements, aka RetrievalMethod, approach.
1399 * When using nested EncryptedKey (Shib 2010) approach, leave null.
1400 * cert:: Certificate containing the public key used to encrypt the symmetric key
1401 * idsuffix:: Use to generate XML ~Id~ attributes for <EncryptedKey> and <EncryptedData>
1402 * return:: Encrypted data as XML data structure. Caller should free this memory. */
1403
1404 /* Called by: zxid_mk_enc_a7n x2, zxid_mk_enc_id x2, zxid_mk_mni x2 */
zxenc_pubkey_enc(zxid_conf * cf,struct zx_str * data,struct zx_xenc_EncryptedKey_s ** ekp,X509 * cert,char * idsuffix,zxid_entity * meta)1405 struct zx_xenc_EncryptedData_s* zxenc_pubkey_enc(zxid_conf* cf, struct zx_str* data, struct zx_xenc_EncryptedKey_s** ekp, X509* cert, char* idsuffix, zxid_entity* meta)
1406 {
1407 struct rsa_st* rsa_pkey;
1408 char symkey[256/8]; /* Large enough for AES256GCM */
1409 struct zx_str symkey_ss;
1410 struct zx_str* ss;
1411 struct zx_str* b64;
1412 struct zx_xenc_EncryptedKey_s* ek = zx_NEW_xenc_EncryptedKey(cf->ctx,0);
1413
1414 ek->Id = zx_attrf(cf->ctx, &ek->gg, zx_Id_ATTR, "EK%s", idsuffix);
1415 ek->EncryptionMethod = zx_NEW_xenc_EncryptionMethod(cf->ctx, &ek->gg);
1416 ek->EncryptionMethod->Algorithm = zx_ref_attr(cf->ctx, &ek->EncryptionMethod->gg, zx_Algorithm_ATTR, ENC_KEYTRAN_ALGO);
1417 ek->KeyInfo = zxid_key_info(cf, &ek->gg, cert);
1418 if (meta && cf->enckey_opt & 0x01) {
1419 /* This hack may help early 2010 vintage Shibboleth SP to work without nested EncryptedKey.
1420 * (personal communication w/Scott 20100906 --Sampo) */
1421 ek->Recipient = zx_dup_attr(cf->ctx, &ek->gg, zx_Recipient_ATTR, meta->eid);
1422 }
1423
1424 if (cf->backwards_compat_ena & ZXID_BACKWARDS_COMPAT_GEN) {
1425 zx_rand(symkey, 128/8); /* AES-128-CBC */
1426 symkey_ss.len = 128/8;
1427 symkey_ss.s = symkey;
1428 } else {
1429 zx_rand(symkey, 256/8); /* AES256GCM */
1430 symkey_ss.len = 256/8;
1431 symkey_ss.s = symkey;
1432 }
1433 rsa_pkey = zx_get_rsa_pub_from_cert(cert, "zxenc_pubkey_enc");
1434 if (!rsa_pkey)
1435 return 0;
1436 /* The padding setting MUST agree with ENC_KEYTRAN_ALGO setting (see near top of this file). */
1437 #if 0
1438 /* PKCS#1 v1.5 padding is vulnearable to known attacks so do not use it. OAEP is better. */
1439 ss = zx_rsa_pub_enc(cf->ctx, &symkey_ss, rsa_pkey, RSA_PKCS1_PADDING);
1440 #else
1441 /* *** IBM did not interop with OAEP padding as of 20071025 */
1442 ss = zx_rsa_pub_enc(cf->ctx, &symkey_ss, rsa_pkey, RSA_PKCS1_OAEP_PADDING);
1443 #endif
1444
1445 b64 = zx_new_len_str(cf->ctx, SIMPLE_BASE64_LEN(ss->len));
1446 base64_fancy_raw(ss->s, ss->len, b64->s, std_basis_64, 0, 0, 0, '=');
1447 zx_str_free(cf->ctx, ss);
1448 ek->CipherData = zx_NEW_xenc_CipherData(cf->ctx, &ek->gg);
1449 ek->CipherData->CipherValue = zx_new_str_elem(cf->ctx, &ek->CipherData->gg, zx_xenc_CipherValue_ELEM, b64);
1450 ek->ReferenceList = zx_NEW_xenc_ReferenceList(cf->ctx, &ek->gg);
1451 ek->ReferenceList->DataReference = zx_NEW_xenc_DataReference(cf->ctx, &ek->ReferenceList->gg);
1452 ek->ReferenceList->DataReference->URI = zx_attrf(cf->ctx, &ek->ReferenceList->DataReference->gg, zx_URI_ATTR, "#ED%s", idsuffix);
1453 zx_reverse_elem_lists(&ek->gg);
1454 if (ekp)
1455 *ekp = ek;
1456
1457 ss = zx_strf(cf->ctx, "ED%s", idsuffix);
1458 return zxenc_symkey_enc(cf, data, ss, &symkey_ss, ek);
1459 }
1460
1461 /* EOF -- zxsig.c */
1462