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