1 /*
2  * XML Security Library (http://www.aleksey.com/xmlsec).
3  *
4  *
5  * This is free software; see Copyright file in the source
6  * distribution for preciese wording.
7  *
8  * Copyright (C) 2010-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9  */
10 /**
11  * SECTION:asymkeys
12  * @Short_description: Asymmetric keys implementation for GCrypt.
13  * @Stability: Private
14  *
15  */
16 
17 #include "globals.h"
18 
19 #include <string.h>
20 
21 #include <gcrypt.h>
22 
23 #include <xmlsec/xmlsec.h>
24 #include <xmlsec/xmltree.h>
25 #include <xmlsec/keys.h>
26 #include <xmlsec/base64.h>
27 #include <xmlsec/keyinfo.h>
28 #include <xmlsec/transforms.h>
29 #include <xmlsec/errors.h>
30 
31 #include <xmlsec/gcrypt/crypto.h>
32 
33 /**************************************************************************
34  *
35  * Helpers
36  *
37  *************************************************************************/
38 static gcry_sexp_t             xmlSecGCryptAsymSExpDup    (gcry_sexp_t sexp);
39 
40 
41 /**************************************************************************
42  *
43  * Internal GCrypt asym key CTX
44  *
45  *************************************************************************/
46 typedef struct _xmlSecGCryptAsymKeyDataCtx       xmlSecGCryptAsymKeyDataCtx,
47                                                 *xmlSecGCryptAsymKeyDataCtxPtr;
48 struct _xmlSecGCryptAsymKeyDataCtx {
49     gcry_sexp_t pub_key;
50     gcry_sexp_t priv_key;
51 };
52 
53 /******************************************************************************
54  *
55  * Asym key (dsa/rsa)
56  *
57  * xmlSecGCryptAsymKeyDataCtx is located after xmlSecTransform
58  *
59  *****************************************************************************/
60 #define xmlSecGCryptAsymKeyDataSize     \
61     (sizeof(xmlSecKeyData) + sizeof(xmlSecGCryptAsymKeyDataCtx))
62 #define xmlSecGCryptAsymKeyDataGetCtx(data) \
63     ((xmlSecGCryptAsymKeyDataCtxPtr)(((xmlSecByte*)(data)) + sizeof(xmlSecKeyData)))
64 
65 static int              xmlSecGCryptAsymKeyDataInitialize       (xmlSecKeyDataPtr data);
66 static int              xmlSecGCryptAsymKeyDataDuplicate        (xmlSecKeyDataPtr dst,
67                                                                  xmlSecKeyDataPtr src);
68 static void             xmlSecGCryptAsymKeyDataFinalize         (xmlSecKeyDataPtr data);
69 
70 static int              xmlSecGCryptAsymKeyDataAdoptKey         (xmlSecKeyDataPtr data,
71                                                                  gcry_sexp_t key_pair);
72 static int              xmlSecGCryptAsymKeyDataAdoptKeyPair     (xmlSecKeyDataPtr data,
73                                                                  gcry_sexp_t pub_key,
74                                                                  gcry_sexp_t priv_key);
75 static gcry_sexp_t      xmlSecGCryptAsymKeyDataGetPublicKey     (xmlSecKeyDataPtr data);
76 static gcry_sexp_t      xmlSecGCryptAsymKeyDataGetPrivateKey    (xmlSecKeyDataPtr data);
77 static int              xmlSecGCryptAsymKeyDataGenerate         (xmlSecKeyDataPtr data,
78                                                                  const char * alg,
79                                                                  xmlSecSize key_size);
80 static xmlSecKeyDataType xmlSecGCryptAsymKeyDataGetType         (xmlSecKeyDataPtr data);
81 static xmlSecSize       xmlSecGCryptAsymKeyDataGetSize          (xmlSecKeyDataPtr data);
82 
83 
84 static int
xmlSecGCryptAsymKeyDataInitialize(xmlSecKeyDataPtr data)85 xmlSecGCryptAsymKeyDataInitialize(xmlSecKeyDataPtr data) {
86     xmlSecGCryptAsymKeyDataCtxPtr ctx;
87 
88     xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
89     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
90 
91     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
92     xmlSecAssert2(ctx != NULL, -1);
93 
94     memset(ctx, 0, sizeof(xmlSecGCryptAsymKeyDataCtx));
95 
96     return(0);
97 }
98 
99 static int
xmlSecGCryptAsymKeyDataDuplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)100 xmlSecGCryptAsymKeyDataDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
101     xmlSecGCryptAsymKeyDataCtxPtr ctxDst;
102     xmlSecGCryptAsymKeyDataCtxPtr ctxSrc;
103 
104     xmlSecAssert2(xmlSecKeyDataIsValid(dst), -1);
105     xmlSecAssert2(xmlSecKeyDataCheckSize(dst, xmlSecGCryptAsymKeyDataSize), -1);
106     xmlSecAssert2(xmlSecKeyDataIsValid(src), -1);
107     xmlSecAssert2(xmlSecKeyDataCheckSize(src, xmlSecGCryptAsymKeyDataSize), -1);
108 
109     ctxDst = xmlSecGCryptAsymKeyDataGetCtx(dst);
110     xmlSecAssert2(ctxDst != NULL, -1);
111     xmlSecAssert2(ctxDst->pub_key == NULL, -1);
112     xmlSecAssert2(ctxDst->priv_key == NULL, -1);
113 
114     ctxSrc = xmlSecGCryptAsymKeyDataGetCtx(src);
115     xmlSecAssert2(ctxSrc != NULL, -1);
116 
117     if(ctxSrc->pub_key != NULL) {
118         ctxDst->pub_key = xmlSecGCryptAsymSExpDup(ctxSrc->pub_key);
119         if(ctxDst->pub_key == NULL) {
120             xmlSecInternalError("xmlSecGCryptAsymSExpDup(pub_key)",
121                                 xmlSecKeyDataGetName(dst));
122             return(-1);
123         }
124     }
125 
126     if(ctxSrc->priv_key != NULL) {
127         ctxDst->priv_key = xmlSecGCryptAsymSExpDup(ctxSrc->priv_key);
128         if(ctxDst->priv_key == NULL) {
129             xmlSecInternalError("xmlSecGCryptAsymSExpDup(priv_key)",
130                                 xmlSecKeyDataGetName(dst));
131             return(-1);
132         }
133     }
134 
135     return(0);
136 }
137 
138 static void
xmlSecGCryptAsymKeyDataFinalize(xmlSecKeyDataPtr data)139 xmlSecGCryptAsymKeyDataFinalize(xmlSecKeyDataPtr data) {
140     xmlSecGCryptAsymKeyDataCtxPtr ctx;
141 
142     xmlSecAssert(xmlSecKeyDataIsValid(data));
143     xmlSecAssert(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize));
144 
145     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
146     xmlSecAssert(ctx != NULL);
147 
148     if(ctx->pub_key != NULL) {
149         gcry_sexp_release(ctx->pub_key);
150     }
151     if(ctx->priv_key != NULL) {
152         gcry_sexp_release(ctx->priv_key);
153     }
154     memset(ctx, 0, sizeof(xmlSecGCryptAsymKeyDataCtx));
155 }
156 
157 static int
xmlSecGCryptAsymKeyDataAdoptKey(xmlSecKeyDataPtr data,gcry_sexp_t key_pair)158 xmlSecGCryptAsymKeyDataAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t key_pair) {
159     xmlSecGCryptAsymKeyDataCtxPtr ctx;
160     gcry_sexp_t pub_key = NULL;
161     gcry_sexp_t priv_key = NULL;
162     int res = -1;
163 
164     xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
165     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
166     xmlSecAssert2(key_pair != NULL, -1);
167 
168     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
169     xmlSecAssert2(ctx != NULL, -1);
170 
171     /* split the key pair, public part should be always present, private might
172        not be present */
173     pub_key = gcry_sexp_find_token(key_pair, "public-key", 0);
174     if(pub_key == NULL) {
175         xmlSecGCryptError("gcry_sexp_find_token(public-key)",
176                           GPG_ERR_NO_ERROR, NULL);
177         goto done;
178     }
179     priv_key = gcry_sexp_find_token(key_pair, "private-key", 0);
180 
181     /* assign */
182     if(xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key) < 0) {
183         xmlSecInternalError("xmlSecGCryptAsymKeyDataAdoptKeyPair", NULL);
184         goto done;
185     }
186     pub_key = NULL; /* data owns it now */
187     priv_key = NULL; /* data owns it now */
188 
189     /* success */
190     res = 0;
191 
192 done:
193     if(pub_key != NULL) {
194         gcry_sexp_release(pub_key);
195     }
196 
197     if(priv_key != NULL) {
198         gcry_sexp_release(priv_key);
199     }
200 
201     /* done */
202     return(res);
203 }
204 
205 static int
xmlSecGCryptAsymKeyDataAdoptKeyPair(xmlSecKeyDataPtr data,gcry_sexp_t pub_key,gcry_sexp_t priv_key)206 xmlSecGCryptAsymKeyDataAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) {
207     xmlSecGCryptAsymKeyDataCtxPtr ctx;
208 
209     xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
210     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
211     xmlSecAssert2(pub_key != NULL, -1); /* public key should present always */
212 /*
213     aleksey - we don't set optional parameters for RSA keys (p, k, u) and
214     because of that we can't actually test the key
215 
216     xmlSecAssert2(((priv_key == NULL) || (gcry_pk_testkey(priv_key) == GPG_ERR_NO_ERROR)), -1);
217 */
218 
219     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
220     xmlSecAssert2(ctx != NULL, -1);
221 
222     /* release prev values and assign new ones */
223     if(ctx->pub_key != NULL) {
224         gcry_sexp_release(ctx->pub_key);
225     }
226     if(ctx->priv_key != NULL) {
227         gcry_sexp_release(ctx->priv_key);
228     }
229 
230     ctx->pub_key = pub_key;
231     ctx->priv_key = priv_key;
232 
233     /* done */
234     return(0);
235 }
236 
237 static gcry_sexp_t
xmlSecGCryptAsymKeyDataGetPublicKey(xmlSecKeyDataPtr data)238 xmlSecGCryptAsymKeyDataGetPublicKey(xmlSecKeyDataPtr data) {
239     xmlSecGCryptAsymKeyDataCtxPtr ctx;
240 
241     xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
242     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), NULL);
243 
244     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
245     xmlSecAssert2(ctx != NULL, NULL);
246 
247     return(ctx->pub_key);
248 }
249 
250 static gcry_sexp_t
xmlSecGCryptAsymKeyDataGetPrivateKey(xmlSecKeyDataPtr data)251 xmlSecGCryptAsymKeyDataGetPrivateKey(xmlSecKeyDataPtr data) {
252     xmlSecGCryptAsymKeyDataCtxPtr ctx;
253 
254     xmlSecAssert2(xmlSecKeyDataIsValid(data), NULL);
255     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), NULL);
256 
257     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
258     xmlSecAssert2(ctx != NULL, NULL);
259 
260     return(ctx->priv_key);
261 }
262 
263 static int
xmlSecGCryptAsymKeyDataGenerate(xmlSecKeyDataPtr data,const char * alg,xmlSecSize key_size)264 xmlSecGCryptAsymKeyDataGenerate(xmlSecKeyDataPtr data, const char * alg, xmlSecSize key_size) {
265     xmlSecGCryptAsymKeyDataCtxPtr ctx;
266     gcry_sexp_t key_spec = NULL;
267     gcry_sexp_t key_pair = NULL;
268     gcry_error_t err;
269     int ret;
270     int res = -1;
271 
272     xmlSecAssert2(xmlSecKeyDataIsValid(data), -1);
273     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), -1);
274     xmlSecAssert2(alg != NULL, -1);
275     xmlSecAssert2(key_size > 0, -1);
276 
277     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
278     xmlSecAssert2(ctx != NULL, -1);
279 
280     err = gcry_sexp_build(&key_spec, NULL,
281                           "(genkey (%s (nbits %d)(transient-key)))",
282                           alg, (int)key_size);
283     if((err != GPG_ERR_NO_ERROR) || (key_spec == NULL)) {
284         xmlSecGCryptError("gcry_sexp_build(genkey)", err, NULL);
285         goto done;
286     }
287 
288     err = gcry_pk_genkey(&key_pair, key_spec);
289     if((err != GPG_ERR_NO_ERROR) || (key_pair == NULL)) {
290         xmlSecGCryptError("gcry_pk_genkey", err, NULL);
291         goto done;
292     }
293 
294     ret = xmlSecGCryptAsymKeyDataAdoptKey(data, key_pair);
295     if(ret < 0) {
296         xmlSecInternalError("xmlSecGCryptAsymKeyDataAdopt", NULL);
297         goto done;
298     }
299     key_pair = NULL; /* now owned by data */
300 
301     /* success */
302     res = 0;
303 
304 done:
305     if(key_spec != NULL) {
306         gcry_sexp_release(key_spec);
307     }
308     if(key_pair != NULL) {
309         gcry_sexp_release(key_pair);
310     }
311 
312     return(res);
313 }
314 
315 static xmlSecKeyDataType
xmlSecGCryptAsymKeyDataGetType(xmlSecKeyDataPtr data)316 xmlSecGCryptAsymKeyDataGetType(xmlSecKeyDataPtr data) {
317     xmlSecGCryptAsymKeyDataCtxPtr ctx;
318 
319     xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
320     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), xmlSecKeyDataTypeUnknown);
321 
322     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
323     xmlSecAssert2(ctx != NULL, xmlSecKeyDataTypeUnknown);
324 
325     if((ctx->priv_key != NULL) && (ctx->pub_key != NULL)) {
326         return (xmlSecKeyDataTypePrivate | xmlSecKeyDataTypePublic);
327     } else if(ctx->pub_key != NULL) {
328         return (xmlSecKeyDataTypePublic);
329     }
330 
331     return (xmlSecKeyDataTypeUnknown);
332 }
333 
334 static xmlSecSize
xmlSecGCryptAsymKeyDataGetSize(xmlSecKeyDataPtr data)335 xmlSecGCryptAsymKeyDataGetSize(xmlSecKeyDataPtr data) {
336     xmlSecGCryptAsymKeyDataCtxPtr ctx;
337 
338     xmlSecAssert2(xmlSecKeyDataIsValid(data), xmlSecKeyDataTypeUnknown);
339     xmlSecAssert2(xmlSecKeyDataCheckSize(data, xmlSecGCryptAsymKeyDataSize), xmlSecKeyDataTypeUnknown);
340 
341     ctx = xmlSecGCryptAsymKeyDataGetCtx(data);
342     xmlSecAssert2(ctx != NULL, 0);
343 
344     /* use pub key since it is more often you have it than not */
345     return (ctx->pub_key != NULL) ? gcry_pk_get_nbits(ctx->pub_key) : 0;
346 }
347 
348 /******************************************************************************
349  *
350  * helper functions
351  *
352  *****************************************************************************/
353 static gcry_sexp_t
xmlSecGCryptAsymSExpDup(gcry_sexp_t pKey)354 xmlSecGCryptAsymSExpDup(gcry_sexp_t pKey) {
355     gcry_sexp_t res = NULL;
356     xmlSecByte *buf = NULL;
357     gcry_error_t err;
358     size_t size;
359 
360     xmlSecAssert2(pKey != NULL, NULL);
361 
362     size = gcry_sexp_sprint(pKey, GCRYSEXP_FMT_ADVANCED, NULL, 0);
363     if(size == 0) {
364         xmlSecGCryptError("gcry_sexp_sprint", GPG_ERR_NO_ERROR, NULL);
365         goto done;
366     }
367 
368     buf = (xmlSecByte *)xmlMalloc(size);
369     if(buf == NULL) {
370         xmlSecMallocError(size, NULL);
371         goto done;
372     }
373 
374     size = gcry_sexp_sprint(pKey, GCRYSEXP_FMT_ADVANCED, buf, size);
375     if(size == 0) {
376         xmlSecGCryptError2("gcry_sexp_sprint", GPG_ERR_NO_ERROR, NULL,
377                            "size=%lu", (unsigned long)size);
378         goto done;
379     }
380 
381     err = gcry_sexp_new(&res, buf, size, 1);
382     if((err != GPG_ERR_NO_ERROR) || (res == NULL)) {
383         xmlSecGCryptError("gcry_sexp_new", err, NULL);
384         goto done;
385     }
386 
387 done:
388     if(buf != NULL) {
389         xmlFree(buf);
390     }
391     return (res);
392 }
393 
394 /**
395  * xmlSecGCryptNodeGetMpiValue:
396  * @cur: the pointer to an XML node.
397  *
398  * Converts the node content from CryptoBinary format
399  * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
400  * to a BIGNUM. If no BIGNUM buffer provided then a new
401  * BIGNUM is created (caller is responsible for freeing it).
402  *
403  * Returns: a pointer to MPI produced from CryptoBinary string
404  * or NULL if an error occurs.
405  */
406 static gcry_mpi_t
xmlSecGCryptNodeGetMpiValue(const xmlNodePtr cur)407 xmlSecGCryptNodeGetMpiValue(const xmlNodePtr cur) {
408     xmlSecBuffer buf;
409     gcry_mpi_t res = NULL;
410     gcry_error_t err;
411     int ret;
412 
413     xmlSecAssert2(cur != NULL, NULL);
414 
415     ret = xmlSecBufferInitialize(&buf, 128);
416     if(ret < 0) {
417         xmlSecInternalError("xmlSecBufferInitialize", NULL);
418         return(NULL);
419     }
420 
421     ret = xmlSecBufferBase64NodeContentRead(&buf, cur);
422     if(ret < 0) {
423         xmlSecInternalError("xmlSecBufferBase64NodeContentRead", NULL);
424         xmlSecBufferFinalize(&buf);
425         return(NULL);
426     }
427 
428     err = gcry_mpi_scan(&res, GCRYMPI_FMT_USG,
429                          xmlSecBufferGetData(&buf),
430                          xmlSecBufferGetSize(&buf),
431                          NULL);
432     if((err != GPG_ERR_NO_ERROR) || (res == NULL)) {
433         xmlSecGCryptError("gcry_mpi_scan", err, NULL);
434         xmlSecBufferFinalize(&buf);
435         return(NULL);
436     }
437 
438     /* done */
439     xmlSecBufferFinalize(&buf);
440     return(res);
441 }
442 
443 /**
444  * xmlSecGCryptNodeSetMpiValue:
445  * @cur: the pointer to an XML node.
446  * @a: the mpi value
447  * @addLineBreaks: if the flag is equal to 1 then
448  *              linebreaks will be added before and after
449  *              new buffer content.
450  *
451  * Converts MPI to CryptoBinary string
452  * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
453  * and sets it as the content of the given node. If the
454  * addLineBreaks is set then line breaks are added
455  * before and after the CryptoBinary string.
456  *
457  * Returns: 0 on success or -1 otherwise.
458  */
459 static int
xmlSecGCryptNodeSetMpiValue(xmlNodePtr cur,const gcry_mpi_t a,int addLineBreaks)460 xmlSecGCryptNodeSetMpiValue(xmlNodePtr cur, const gcry_mpi_t a, int addLineBreaks) {
461     xmlSecBuffer buf;
462     gcry_error_t err;
463     size_t written = 0;
464     int ret;
465 
466     xmlSecAssert2(a != NULL, -1);
467     xmlSecAssert2(cur != NULL, -1);
468 
469     written = 0;
470     err = gcry_mpi_print(GCRYMPI_FMT_USG, NULL, 0, &written, a);
471     if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
472         xmlSecGCryptError("gcry_mpi_print", err, NULL);
473         return(-1);
474     }
475 
476     ret = xmlSecBufferInitialize(&buf, written + 1);
477     if(ret < 0) {
478         xmlSecInternalError2("xmlSecBufferInitialize", NULL,
479                              "size=%d", (int)written + 1);
480         return(-1);
481     }
482 
483     written = 0;
484     err = gcry_mpi_print(GCRYMPI_FMT_USG,
485             xmlSecBufferGetData(&buf),
486             xmlSecBufferGetMaxSize(&buf),
487             &written, a);
488     if((err != GPG_ERR_NO_ERROR) || (written == 0)) {
489         xmlSecGCryptError("gcry_mpi_print", err, NULL);
490         xmlSecBufferFinalize(&buf);
491         return(-1);
492     }
493 
494     ret = xmlSecBufferSetSize(&buf, written);
495     if(ret < 0) {
496         xmlSecInternalError2("xmlSecBufferSetSize", NULL,
497                              "size=%d", (int)written);
498         xmlSecBufferFinalize(&buf);
499         return(-1);
500     }
501 
502     if(addLineBreaks) {
503         xmlNodeSetContent(cur, xmlSecGetDefaultLineFeed());
504     } else {
505         xmlNodeSetContent(cur, xmlSecStringEmpty);
506     }
507 
508     ret = xmlSecBufferBase64NodeContentWrite(&buf, cur, xmlSecBase64GetDefaultLineSize());
509     if(ret < 0) {
510         xmlSecInternalError("xmlSecBufferBase64NodeContentWrite", NULL);
511         xmlSecBufferFinalize(&buf);
512         return(-1);
513     }
514 
515     if(addLineBreaks) {
516         xmlNodeAddContent(cur, xmlSecGetDefaultLineFeed());
517     }
518 
519     xmlSecBufferFinalize(&buf);
520     return(0);
521 }
522 
523 /**
524  * xmlSecGCryptNodeSetSExpTokValue:
525  * @cur: the pointer to an XML node.
526  * @sexp: the sexp
527  * @tok: the token
528  * @addLineBreaks: if the flag is equal to 1 then
529  *              linebreaks will be added before and after
530  *              new buffer content.
531  *
532  * Converts MPI to CryptoBinary string
533  * (http://www.w3.org/TR/xmldsig-core/#sec-CryptoBinary)
534  * and sets it as the content of the given node. If the
535  * addLineBreaks is set then line breaks are added
536  * before and after the CryptoBinary string.
537  *
538  * Returns: 0 on success or -1 otherwise.
539  */
540 static int
xmlSecGCryptNodeSetSExpTokValue(xmlNodePtr cur,const gcry_sexp_t sexp,const char * tok,int addLineBreaks)541 xmlSecGCryptNodeSetSExpTokValue(xmlNodePtr cur, const gcry_sexp_t sexp,
542                                 const char * tok, int addLineBreaks)
543 {
544     gcry_sexp_t val = NULL;
545     gcry_mpi_t mpi = NULL;
546     int res = -1;
547 
548     xmlSecAssert2(cur != NULL, -1);
549     xmlSecAssert2(sexp != NULL, -1);
550     xmlSecAssert2(tok != NULL, -1);
551 
552     val = gcry_sexp_find_token(sexp, tok, 0);
553     if(val == NULL) {
554         xmlSecGCryptError2("gcry_sexp_find_token", GPG_ERR_NO_ERROR, NULL,
555                            "tok=%s", xmlSecErrorsSafeString(tok));
556         goto done;
557     }
558 
559     mpi = gcry_sexp_nth_mpi(val, 1, GCRYMPI_FMT_USG);
560     if(mpi == NULL) {
561         xmlSecGCryptError("gcry_sexp_nth_mpi", GPG_ERR_NO_ERROR, NULL);
562         goto done;
563     }
564 
565     /* almost done */
566     res = xmlSecGCryptNodeSetMpiValue(cur, mpi, addLineBreaks);
567 
568 done:
569     if(mpi != NULL) {
570         gcry_mpi_release(mpi);
571     }
572     if(val != NULL) {
573         gcry_sexp_release(val);
574     }
575 
576     return(res);
577 }
578 
579 #ifndef XMLSEC_NO_DSA
580 /**************************************************************************
581  *
582  * <dsig:DSAKeyValue> processing
583  *
584  *
585  * The DSAKeyValue Element (http://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue)
586  *
587  * DSA keys and the DSA signature algorithm are specified in [DSS].
588  * DSA public key values can have the following fields:
589  *
590  *   * P - a prime modulus meeting the [DSS] requirements
591  *   * Q - an integer in the range 2**159 < Q < 2**160 which is a prime
592  *         divisor of P-1
593  *   * G - an integer with certain properties with respect to P and Q
594  *   * Y - G**X mod P (where X is part of the private key and not made
595  *         public)
596  *   * J - (P - 1) / Q
597  *   * seed - a DSA prime generation seed
598  *   * pgenCounter - a DSA prime generation counter
599  *
600  * Parameter J is available for inclusion solely for efficiency as it is
601  * calculatable from P and Q. Parameters seed and pgenCounter are used in the
602  * DSA prime number generation algorithm specified in [DSS]. As such, they are
603  * optional but must either both be present or both be absent. This prime
604  * generation algorithm is designed to provide assurance that a weak prime is
605  * not being used and it yields a P and Q value. Parameters P, Q, and G can be
606  * public and common to a group of users. They might be known from application
607  * context. As such, they are optional but P and Q must either both appear or
608  * both be absent. If all of P, Q, seed, and pgenCounter are present,
609  * implementations are not required to check if they are consistent and are
610  * free to use either P and Q or seed and pgenCounter. All parameters are
611  * encoded as base64 [MIME] values.
612  *
613  * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
614  * represented in XML as octet strings as defined by the ds:CryptoBinary type.
615  *
616  * Schema Definition:
617  *
618  * <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
619  * <complexType name="DSAKeyValueType">
620  *   <sequence>
621  *     <sequence minOccurs="0">
622  *        <element name="P" type="ds:CryptoBinary"/>
623  *        <element name="Q" type="ds:CryptoBinary"/>
624  *     </sequence>
625  *     <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
626  *     <element name="Y" type="ds:CryptoBinary"/>
627  *     <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
628  *     <sequence minOccurs="0">
629  *       <element name="Seed" type="ds:CryptoBinary"/>
630  *       <element name="PgenCounter" type="ds:CryptoBinary"/>
631  *     </sequence>
632  *   </sequence>
633  * </complexType>
634  *
635  * DTD Definition:
636  *
637  *  <!ELEMENT DSAKeyValue ((P, Q)?, G?, Y, J?, (Seed, PgenCounter)?) >
638  *  <!ELEMENT P (#PCDATA) >
639  *  <!ELEMENT Q (#PCDATA) >
640  *  <!ELEMENT G (#PCDATA) >
641  *  <!ELEMENT Y (#PCDATA) >
642  *  <!ELEMENT J (#PCDATA) >
643  *  <!ELEMENT Seed (#PCDATA) >
644  *  <!ELEMENT PgenCounter (#PCDATA) >
645  *
646  * ============================================================================
647  *
648  * To support reading/writing private keys an X element added (before Y).
649  * todo: The current implementation does not support Seed and PgenCounter!
650  * by this the P, Q and G are *required*!
651  *
652  *************************************************************************/
653 static int              xmlSecGCryptKeyDataDsaInitialize        (xmlSecKeyDataPtr data);
654 static int              xmlSecGCryptKeyDataDsaDuplicate         (xmlSecKeyDataPtr dst,
655                                                                  xmlSecKeyDataPtr src);
656 static void             xmlSecGCryptKeyDataDsaFinalize          (xmlSecKeyDataPtr data);
657 static int              xmlSecGCryptKeyDataDsaXmlRead           (xmlSecKeyDataId id,
658                                                                  xmlSecKeyPtr key,
659                                                                  xmlNodePtr node,
660                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
661 static int              xmlSecGCryptKeyDataDsaXmlWrite          (xmlSecKeyDataId id,
662                                                                  xmlSecKeyPtr key,
663                                                                  xmlNodePtr node,
664                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
665 static int              xmlSecGCryptKeyDataDsaGenerate          (xmlSecKeyDataPtr data,
666                                                                  xmlSecSize sizeBits,
667                                                                  xmlSecKeyDataType type);
668 
669 static xmlSecKeyDataType xmlSecGCryptKeyDataDsaGetType          (xmlSecKeyDataPtr data);
670 static xmlSecSize       xmlSecGCryptKeyDataDsaGetSize           (xmlSecKeyDataPtr data);
671 static void             xmlSecGCryptKeyDataDsaDebugDump         (xmlSecKeyDataPtr data,
672                                                                  FILE* output);
673 static void             xmlSecGCryptKeyDataDsaDebugXmlDump      (xmlSecKeyDataPtr data,
674                                                                  FILE* output);
675 
676 static xmlSecKeyDataKlass xmlSecGCryptKeyDataDsaKlass = {
677     sizeof(xmlSecKeyDataKlass),
678     xmlSecGCryptAsymKeyDataSize,
679 
680     /* data */
681     xmlSecNameDSAKeyValue,
682     xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
683                                                 /* xmlSecKeyDataUsage usage; */
684     xmlSecHrefDSAKeyValue,                      /* const xmlChar* href; */
685     xmlSecNodeDSAKeyValue,                      /* const xmlChar* dataNodeName; */
686     xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
687 
688     /* constructors/destructor */
689     xmlSecGCryptKeyDataDsaInitialize,          /* xmlSecKeyDataInitializeMethod initialize; */
690     xmlSecGCryptKeyDataDsaDuplicate,           /* xmlSecKeyDataDuplicateMethod duplicate; */
691     xmlSecGCryptKeyDataDsaFinalize,            /* xmlSecKeyDataFinalizeMethod finalize; */
692     xmlSecGCryptKeyDataDsaGenerate,            /* xmlSecKeyDataGenerateMethod generate; */
693 
694     /* get info */
695     xmlSecGCryptKeyDataDsaGetType,             /* xmlSecKeyDataGetTypeMethod getType; */
696     xmlSecGCryptKeyDataDsaGetSize,             /* xmlSecKeyDataGetSizeMethod getSize; */
697     NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */
698 
699     /* read/write */
700     xmlSecGCryptKeyDataDsaXmlRead,             /* xmlSecKeyDataXmlReadMethod xmlRead; */
701     xmlSecGCryptKeyDataDsaXmlWrite,            /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
702     NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
703     NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
704 
705     /* debug */
706     xmlSecGCryptKeyDataDsaDebugDump,           /* xmlSecKeyDataDebugDumpMethod debugDump; */
707     xmlSecGCryptKeyDataDsaDebugXmlDump,        /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
708 
709     /* reserved for the future */
710     NULL,                                       /* void* reserved0; */
711     NULL,                                       /* void* reserved1; */
712 };
713 
714 /**
715  * xmlSecGCryptKeyDataDsaGetKlass:
716  *
717  * The DSA key data klass.
718  *
719  * Returns: pointer to DSA key data klass.
720  */
721 xmlSecKeyDataId
xmlSecGCryptKeyDataDsaGetKlass(void)722 xmlSecGCryptKeyDataDsaGetKlass(void) {
723     return(&xmlSecGCryptKeyDataDsaKlass);
724 }
725 
726 /**
727  * xmlSecGCryptKeyDataDsaAdoptKey:
728  * @data:               the pointer to DSA key data.
729  * @dsa_key:            the pointer to GCrypt DSA key.
730  *
731  * Sets the value of DSA key data.
732  *
733  * Returns: 0 on success or a negative value otherwise.
734  */
735 int
xmlSecGCryptKeyDataDsaAdoptKey(xmlSecKeyDataPtr data,gcry_sexp_t dsa_key)736 xmlSecGCryptKeyDataDsaAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t dsa_key) {
737     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
738     xmlSecAssert2(dsa_key != NULL, -1);
739 
740     return xmlSecGCryptAsymKeyDataAdoptKey(data, dsa_key);
741 }
742 
743 
744 /**
745  * xmlSecGCryptKeyDataDsaAdoptKeyPair:
746  * @data:               the pointer to DSA key data.
747  * @pub_key:            the pointer to GCrypt DSA pub key.
748  * @priv_key:           the pointer to GCrypt DSA priv key.
749  *
750  * Sets the value of DSA key data.
751  *
752  * Returns: 0 on success or a negative value otherwise.
753  */
754 int
xmlSecGCryptKeyDataDsaAdoptKeyPair(xmlSecKeyDataPtr data,gcry_sexp_t pub_key,gcry_sexp_t priv_key)755 xmlSecGCryptKeyDataDsaAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) {
756     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
757     xmlSecAssert2(pub_key != NULL, -1);
758 
759     return xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key);
760 }
761 
762 /**
763  * xmlSecGCryptKeyDataDsaGetPublicKey:
764  * @data:               the pointer to DSA key data.
765  *
766  * Gets the GCrypt DSA public key from DSA key data.
767  *
768  * Returns: pointer to GCrypt public DSA key or NULL if an error occurs.
769  */
770 gcry_sexp_t
xmlSecGCryptKeyDataDsaGetPublicKey(xmlSecKeyDataPtr data)771 xmlSecGCryptKeyDataDsaGetPublicKey(xmlSecKeyDataPtr data) {
772     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), NULL);
773     return xmlSecGCryptAsymKeyDataGetPublicKey(data);
774 }
775 
776 /**
777  * xmlSecGCryptKeyDataDsaGetPrivateKey:
778  * @data:               the pointer to DSA key data.
779  *
780  * Gets the GCrypt DSA private key from DSA key data.
781  *
782  * Returns: pointer to GCrypt private DSA key or NULL if an error occurs.
783  */
784 gcry_sexp_t
xmlSecGCryptKeyDataDsaGetPrivateKey(xmlSecKeyDataPtr data)785 xmlSecGCryptKeyDataDsaGetPrivateKey(xmlSecKeyDataPtr data) {
786     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), NULL);
787     return xmlSecGCryptAsymKeyDataGetPrivateKey(data);
788 }
789 
790 static int
xmlSecGCryptKeyDataDsaInitialize(xmlSecKeyDataPtr data)791 xmlSecGCryptKeyDataDsaInitialize(xmlSecKeyDataPtr data) {
792     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
793 
794     return(xmlSecGCryptAsymKeyDataInitialize(data));
795 }
796 
797 static int
xmlSecGCryptKeyDataDsaDuplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)798 xmlSecGCryptKeyDataDsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
799     xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGCryptKeyDataDsaId), -1);
800     xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGCryptKeyDataDsaId), -1);
801 
802     return(xmlSecGCryptAsymKeyDataDuplicate(dst, src));
803 }
804 
805 static void
xmlSecGCryptKeyDataDsaFinalize(xmlSecKeyDataPtr data)806 xmlSecGCryptKeyDataDsaFinalize(xmlSecKeyDataPtr data) {
807     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId));
808 
809     xmlSecGCryptAsymKeyDataFinalize(data);
810 }
811 
812 static int
xmlSecGCryptKeyDataDsaGenerate(xmlSecKeyDataPtr data,xmlSecSize sizeBits,xmlSecKeyDataType type ATTRIBUTE_UNUSED)813 xmlSecGCryptKeyDataDsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
814     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), -1);
815     xmlSecAssert2(sizeBits > 0, -1);
816 
817     return xmlSecGCryptAsymKeyDataGenerate(data, "dsa", sizeBits);
818 }
819 
820 static xmlSecKeyDataType
xmlSecGCryptKeyDataDsaGetType(xmlSecKeyDataPtr data)821 xmlSecGCryptKeyDataDsaGetType(xmlSecKeyDataPtr data) {
822     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), xmlSecKeyDataTypeUnknown);
823 
824     return xmlSecGCryptAsymKeyDataGetType(data);
825 }
826 
827 static xmlSecSize
xmlSecGCryptKeyDataDsaGetSize(xmlSecKeyDataPtr data)828 xmlSecGCryptKeyDataDsaGetSize(xmlSecKeyDataPtr data) {
829     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId), 0);
830 
831     return xmlSecGCryptAsymKeyDataGetSize(data);
832 }
833 
834 static void
xmlSecGCryptKeyDataDsaDebugDump(xmlSecKeyDataPtr data,FILE * output)835 xmlSecGCryptKeyDataDsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
836     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId));
837     xmlSecAssert(output != NULL);
838 
839     fprintf(output, "=== dsa key: size = %d\n",
840             xmlSecGCryptKeyDataDsaGetSize(data));
841 }
842 
843 static void
xmlSecGCryptKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data,FILE * output)844 xmlSecGCryptKeyDataDsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
845     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataDsaId));
846     xmlSecAssert(output != NULL);
847 
848     fprintf(output, "<DSAKeyValue size=\"%d\" />\n",
849             xmlSecGCryptKeyDataDsaGetSize(data));
850 }
851 
852 static int
xmlSecGCryptKeyDataDsaXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)853 xmlSecGCryptKeyDataDsaXmlRead(xmlSecKeyDataId id,
854                               xmlSecKeyPtr key,
855                               xmlNodePtr node,
856                               xmlSecKeyInfoCtxPtr keyInfoCtx)
857 {
858     xmlNodePtr cur;
859     xmlSecKeyDataPtr data = NULL;
860     gcry_mpi_t p = NULL;
861     gcry_mpi_t q = NULL;
862     gcry_mpi_t g = NULL;
863     gcry_mpi_t x = NULL;
864     gcry_mpi_t y = NULL;
865     gcry_sexp_t pub_key = NULL;
866     gcry_sexp_t priv_key = NULL;
867     gcry_error_t err;
868     int res = -1;
869     int ret;
870 
871     xmlSecAssert2(id == xmlSecGCryptKeyDataDsaId, -1);
872     xmlSecAssert2(key != NULL, -1);
873     xmlSecAssert2(node != NULL, -1);
874     xmlSecAssert2(keyInfoCtx != NULL, -1);
875 
876     if(xmlSecKeyGetValue(key) != NULL) {
877         xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_KEY_DATA,
878                          xmlSecKeyDataKlassGetName(id),
879                          "key already has a value");
880         goto done;
881     }
882 
883     cur = xmlSecGetNextElementNode(node->children);
884 
885     /* first is P node. It is REQUIRED because we do not support Seed and PgenCounter*/
886     if((cur == NULL) || (!xmlSecCheckNodeName(cur,  xmlSecNodeDSAP, xmlSecDSigNs))) {
887         xmlSecInvalidNodeError(cur, xmlSecNodeDSAP, xmlSecKeyDataKlassGetName(id));
888         goto done;
889     }
890     p = xmlSecGCryptNodeGetMpiValue(cur);
891     if(p == NULL) {
892         xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeDSAP)",
893                             xmlSecKeyDataKlassGetName(id));
894         goto done;
895     }
896     cur = xmlSecGetNextElementNode(cur->next);
897 
898     /* next is Q node. It is REQUIRED because we do not support Seed and PgenCounter*/
899     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAQ, xmlSecDSigNs))) {
900         xmlSecInvalidNodeError(cur, xmlSecNodeDSAQ, xmlSecKeyDataKlassGetName(id));
901         goto done;
902     }
903     q = xmlSecGCryptNodeGetMpiValue(cur);
904     if(q == NULL) {
905         xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeDSAQ)",
906                             xmlSecKeyDataKlassGetName(id));
907         goto done;
908     }
909     cur = xmlSecGetNextElementNode(cur->next);
910 
911     /* next is G node. It is REQUIRED because we do not support Seed and PgenCounter*/
912     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAG, xmlSecDSigNs))) {
913         xmlSecInvalidNodeError(cur, xmlSecNodeDSAG, xmlSecKeyDataKlassGetName(id));
914         goto done;
915     }
916     g = xmlSecGCryptNodeGetMpiValue(cur);
917     if(g == NULL) {
918         xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeDSAG)",
919                             xmlSecKeyDataKlassGetName(id));
920         goto done;
921     }
922     cur = xmlSecGetNextElementNode(cur->next);
923 
924     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAX, xmlSecNs))) {
925         /* next is X node. It is REQUIRED for private key but
926          * we are not sure exactly what do we read */
927         x = xmlSecGCryptNodeGetMpiValue(cur);
928         if(x == NULL) {
929             xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeDSAX)",
930                                 xmlSecKeyDataKlassGetName(id));
931             goto done;
932         }
933         cur = xmlSecGetNextElementNode(cur->next);
934     }
935 
936     /* next is Y node. */
937     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeDSAY, xmlSecDSigNs))) {
938         xmlSecInvalidNodeError(cur, xmlSecNodeDSAY, xmlSecKeyDataKlassGetName(id));
939         goto done;
940     }
941     y = xmlSecGCryptNodeGetMpiValue(cur);
942     if(y == NULL) {
943         xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeDSAY)",
944                             xmlSecKeyDataKlassGetName(id));
945         goto done;
946     }
947     cur = xmlSecGetNextElementNode(cur->next);
948 
949     /* todo: add support for J */
950     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAJ, xmlSecDSigNs))) {
951         cur = xmlSecGetNextElementNode(cur->next);
952     }
953 
954     /* todo: add support for seed */
955     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSASeed, xmlSecDSigNs))) {
956         cur = xmlSecGetNextElementNode(cur->next);
957     }
958 
959     /* todo: add support for pgencounter */
960     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeDSAPgenCounter, xmlSecDSigNs))) {
961         cur = xmlSecGetNextElementNode(cur->next);
962     }
963 
964     if(cur != NULL) {
965         xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(id));
966         goto done;
967     }
968 
969     /* Convert from OpenSSL parameter ordering to the OpenPGP order. */
970     /* First check that x < y; if not swap x and y  */
971     if((x != NULL) && (gcry_mpi_cmp (x, y) > 0)) {
972         gcry_mpi_swap (x, y);
973     }
974 
975     /* construct pub/priv key pairs */
976     err = gcry_sexp_build(&pub_key, NULL,
977              "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
978              p, q, g, y);
979     if((err != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
980         xmlSecGCryptError("gcry_sexp_build(public)", err,
981                           xmlSecKeyDataGetName(data));
982         goto done;
983     }
984     if(x != NULL) {
985         err = gcry_sexp_build(&priv_key, NULL,
986                  "(private-key(dsa(p%m)(q%m)(g%m)(x%m)(y%m)))",
987                  p, q, g, x, y);
988         if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
989             xmlSecGCryptError("gcry_sexp_build(private)", err,
990                               xmlSecKeyDataGetName(data));
991             goto done;
992         }
993     }
994 
995     /* create key data */
996     data = xmlSecKeyDataCreate(id);
997     if(data == NULL ) {
998         xmlSecInternalError("xmlSecKeyDataCreate",
999                             xmlSecKeyDataKlassGetName(id));
1000         goto done;
1001     }
1002 
1003     ret = xmlSecGCryptKeyDataDsaAdoptKeyPair(data, pub_key, priv_key);
1004     if(ret < 0) {
1005         xmlSecInternalError("xmlSecGCryptKeyDataDsaAdoptKeyPair",
1006                             xmlSecKeyDataGetName(data));
1007         goto done;
1008     }
1009     pub_key = NULL; /* pub_key is owned by data now */
1010     priv_key = NULL; /* priv_key is owned by data now */
1011 
1012     /* set key */
1013     ret = xmlSecKeySetValue(key, data);
1014     if(ret < 0) {
1015         xmlSecInternalError("xmlSecKeySetValue",
1016                             xmlSecKeyDataGetName(data));
1017         goto done;
1018     }
1019     data = NULL; /* data is owned by key now */
1020 
1021     /* success */
1022     res = 0;
1023 
1024 done:
1025     /* cleanup */
1026     if(p != NULL) {
1027         gcry_mpi_release(p);
1028     }
1029 
1030     if(q != NULL) {
1031         gcry_mpi_release(q);
1032     }
1033 
1034     if(g != NULL) {
1035         gcry_mpi_release(g);
1036     }
1037 
1038     if(x != NULL) {
1039         gcry_mpi_release(x);
1040     }
1041 
1042     if(y != NULL) {
1043         gcry_mpi_release(y);
1044     }
1045 
1046     if(pub_key != NULL) {
1047         gcry_sexp_release(pub_key);
1048     }
1049 
1050     if(priv_key != NULL) {
1051         gcry_sexp_release(priv_key);
1052     }
1053 
1054     if(data != NULL) {
1055         xmlSecKeyDataDestroy(data);
1056     }
1057     return(res);
1058 }
1059 
1060 static int
xmlSecGCryptKeyDataDsaXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1061 xmlSecGCryptKeyDataDsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
1062                                 xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1063     xmlNodePtr cur;
1064     gcry_sexp_t pub_priv_key;
1065     gcry_sexp_t dsa = NULL;
1066     int private = 0;
1067     int res = -1;
1068     int ret;
1069 
1070     xmlSecAssert2(id == xmlSecGCryptKeyDataDsaId, -1);
1071     xmlSecAssert2(key != NULL, -1);
1072     xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataDsaId), -1);
1073     xmlSecAssert2(node != NULL, -1);
1074     xmlSecAssert2(keyInfoCtx != NULL, -1);
1075 
1076     if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
1077         /* we can have only private key or public key */
1078         return(0);
1079     }
1080 
1081     /* find the private or public key */
1082     pub_priv_key = xmlSecGCryptKeyDataDsaGetPrivateKey(xmlSecKeyGetValue(key));
1083     if(pub_priv_key == NULL) {
1084         pub_priv_key = xmlSecGCryptKeyDataDsaGetPublicKey(xmlSecKeyGetValue(key));
1085         if(pub_priv_key == NULL) {
1086             xmlSecInternalError("xmlSecGCryptKeyDataDsaGetPublicKey()",
1087                                 xmlSecKeyDataKlassGetName(id));
1088             goto done;
1089         }
1090     } else {
1091         private = 1;
1092     }
1093 
1094     dsa = gcry_sexp_find_token(pub_priv_key, "dsa", 0);
1095     if(dsa == NULL) {
1096         xmlSecGCryptError("gcry_sexp_find_token(dsa)", GPG_ERR_NO_ERROR,
1097                           xmlSecKeyDataKlassGetName(id));
1098         goto done;
1099     }
1100 
1101     /* first is P node */
1102     cur = xmlSecAddChild(node, xmlSecNodeDSAP, xmlSecDSigNs);
1103     if(cur == NULL) {
1104         xmlSecInternalError("xmlSecAddChild(NodeDSAP)",
1105                              xmlSecKeyDataKlassGetName(id));
1106         goto done;
1107     }
1108     ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "p", 1);
1109     if(ret < 0) {
1110         xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeDSAP)",
1111                             xmlSecKeyDataKlassGetName(id));
1112         goto done;
1113     }
1114 
1115     /* next is Q node. */
1116     cur = xmlSecAddChild(node, xmlSecNodeDSAQ, xmlSecDSigNs);
1117     if(cur == NULL) {
1118         xmlSecInternalError("xmlSecAddChild(NodeDSAQ)",
1119                             xmlSecKeyDataKlassGetName(id));
1120         goto done;
1121     }
1122     ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "q", 1);
1123     if(ret < 0) {
1124         xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeDSAQ)",
1125                             xmlSecKeyDataKlassGetName(id));
1126         goto done;
1127     }
1128 
1129     /* next is G node. */
1130     cur = xmlSecAddChild(node, xmlSecNodeDSAG, xmlSecDSigNs);
1131     if(cur == NULL) {
1132         xmlSecInternalError("xmlSecAddChild(NodeDSAG)",
1133                             xmlSecKeyDataKlassGetName(id));
1134         goto done;
1135     }
1136     ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "g", 1);
1137     if(ret < 0) {
1138         xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeDSAG)",
1139                             xmlSecKeyDataKlassGetName(id));
1140         goto done;
1141     }
1142 
1143     /* next is X node: write it ONLY for private keys and ONLY if it is requested */
1144     if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (private != 0)) {
1145         cur = xmlSecAddChild(node, xmlSecNodeDSAX, xmlSecNs);
1146         if(cur == NULL) {
1147             xmlSecInternalError("xmlSecAddChild(NodeDSAX)",
1148                                 xmlSecKeyDataKlassGetName(id));
1149             goto done;
1150         }
1151         ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "x", 1);
1152         if(ret < 0) {
1153             xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeDSAX)",
1154                                 xmlSecKeyDataKlassGetName(id));
1155             goto done;
1156         }
1157     }
1158 
1159     /* next is Y node. */
1160     cur = xmlSecAddChild(node, xmlSecNodeDSAY, xmlSecDSigNs);
1161     if(cur == NULL) {
1162         xmlSecInternalError("xmlSecAddChild(NodeDSAY)",
1163                             xmlSecKeyDataKlassGetName(id));
1164         goto done;
1165     }
1166     ret = xmlSecGCryptNodeSetSExpTokValue(cur, dsa, "y", 1);
1167     if(ret < 0) {
1168         xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeDSAY)",
1169                             xmlSecKeyDataKlassGetName(id));
1170         goto done;
1171     }
1172 
1173     /* success */
1174     res = 0;
1175 
1176 done:
1177     if(dsa != NULL) {
1178         gcry_sexp_release(dsa);
1179     }
1180 
1181     return(res);
1182 }
1183 
1184 #endif /* XMLSEC_NO_DSA */
1185 
1186 
1187 #ifndef XMLSEC_NO_RSA
1188 /**************************************************************************
1189  *
1190  * <dsig:RSAKeyValue> processing
1191  *
1192  * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
1193  * The RSAKeyValue Element
1194  *
1195  * RSA key values have two fields: Modulus and Exponent.
1196  *
1197  * <RSAKeyValue>
1198  *   <Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W
1199  *     jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
1200  *        5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
1201  *   </Modulus>
1202  *   <Exponent>AQAB</Exponent>
1203  * </RSAKeyValue>
1204  *
1205  * Arbitrary-length integers (e.g. "bignums" such as RSA moduli) are
1206  * represented in XML as octet strings as defined by the ds:CryptoBinary type.
1207  *
1208  * Schema Definition:
1209  *
1210  * <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
1211  * <complexType name="RSAKeyValueType">
1212  *   <sequence>
1213  *     <element name="Modulus" type="ds:CryptoBinary"/>
1214  *     <element name="Exponent" type="ds:CryptoBinary"/>
1215  *   </sequence>
1216  * </complexType>
1217  *
1218  * DTD Definition:
1219  *
1220  * <!ELEMENT RSAKeyValue (Modulus, Exponent) >
1221  * <!ELEMENT Modulus (#PCDATA) >
1222  * <!ELEMENT Exponent (#PCDATA) >
1223  *
1224  * ============================================================================
1225  *
1226  * To support reading/writing private keys an PrivateExponent element is added
1227  * to the end
1228  *
1229  *************************************************************************/
1230 
1231 static int              xmlSecGCryptKeyDataRsaInitialize       (xmlSecKeyDataPtr data);
1232 static int              xmlSecGCryptKeyDataRsaDuplicate        (xmlSecKeyDataPtr dst,
1233                                                                  xmlSecKeyDataPtr src);
1234 static void             xmlSecGCryptKeyDataRsaFinalize         (xmlSecKeyDataPtr data);
1235 static int              xmlSecGCryptKeyDataRsaXmlRead          (xmlSecKeyDataId id,
1236                                                                  xmlSecKeyPtr key,
1237                                                                  xmlNodePtr node,
1238                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
1239 static int              xmlSecGCryptKeyDataRsaXmlWrite         (xmlSecKeyDataId id,
1240                                                                  xmlSecKeyPtr key,
1241                                                                  xmlNodePtr node,
1242                                                                  xmlSecKeyInfoCtxPtr keyInfoCtx);
1243 static int              xmlSecGCryptKeyDataRsaGenerate         (xmlSecKeyDataPtr data,
1244                                                                  xmlSecSize sizeBits,
1245                                                                  xmlSecKeyDataType type);
1246 
1247 static xmlSecKeyDataType xmlSecGCryptKeyDataRsaGetType         (xmlSecKeyDataPtr data);
1248 static xmlSecSize               xmlSecGCryptKeyDataRsaGetSize          (xmlSecKeyDataPtr data);
1249 static void             xmlSecGCryptKeyDataRsaDebugDump        (xmlSecKeyDataPtr data,
1250                                                                  FILE* output);
1251 static void             xmlSecGCryptKeyDataRsaDebugXmlDump     (xmlSecKeyDataPtr data,
1252                                                                  FILE* output);
1253 static xmlSecKeyDataKlass xmlSecGCryptKeyDataRsaKlass = {
1254     sizeof(xmlSecKeyDataKlass),
1255     xmlSecGCryptAsymKeyDataSize,
1256 
1257     /* data */
1258     xmlSecNameRSAKeyValue,
1259     xmlSecKeyDataUsageKeyValueNode | xmlSecKeyDataUsageRetrievalMethodNodeXml,
1260                                                 /* xmlSecKeyDataUsage usage; */
1261     xmlSecHrefRSAKeyValue,                      /* const xmlChar* href; */
1262     xmlSecNodeRSAKeyValue,                      /* const xmlChar* dataNodeName; */
1263     xmlSecDSigNs,                               /* const xmlChar* dataNodeNs; */
1264 
1265     /* constructors/destructor */
1266     xmlSecGCryptKeyDataRsaInitialize,          /* xmlSecKeyDataInitializeMethod initialize; */
1267     xmlSecGCryptKeyDataRsaDuplicate,           /* xmlSecKeyDataDuplicateMethod duplicate; */
1268     xmlSecGCryptKeyDataRsaFinalize,            /* xmlSecKeyDataFinalizeMethod finalize; */
1269     xmlSecGCryptKeyDataRsaGenerate,            /* xmlSecKeyDataGenerateMethod generate; */
1270 
1271     /* get info */
1272     xmlSecGCryptKeyDataRsaGetType,             /* xmlSecKeyDataGetTypeMethod getType; */
1273     xmlSecGCryptKeyDataRsaGetSize,             /* xmlSecKeyDataGetSizeMethod getSize; */
1274     NULL,                                       /* xmlSecKeyDataGetIdentifier getIdentifier; */
1275 
1276     /* read/write */
1277     xmlSecGCryptKeyDataRsaXmlRead,             /* xmlSecKeyDataXmlReadMethod xmlRead; */
1278     xmlSecGCryptKeyDataRsaXmlWrite,            /* xmlSecKeyDataXmlWriteMethod xmlWrite; */
1279     NULL,                                       /* xmlSecKeyDataBinReadMethod binRead; */
1280     NULL,                                       /* xmlSecKeyDataBinWriteMethod binWrite; */
1281 
1282     /* debug */
1283     xmlSecGCryptKeyDataRsaDebugDump,           /* xmlSecKeyDataDebugDumpMethod debugDump; */
1284     xmlSecGCryptKeyDataRsaDebugXmlDump,        /* xmlSecKeyDataDebugDumpMethod debugXmlDump; */
1285 
1286     /* reserved for the future */
1287     NULL,                                       /* void* reserved0; */
1288     NULL,                                       /* void* reserved1; */
1289 };
1290 
1291 /**
1292  * xmlSecGCryptKeyDataRsaGetKlass:
1293  *
1294  * The GCrypt RSA key data klass.
1295  *
1296  * Returns: pointer to GCrypt RSA key data klass.
1297  */
1298 xmlSecKeyDataId
xmlSecGCryptKeyDataRsaGetKlass(void)1299 xmlSecGCryptKeyDataRsaGetKlass(void) {
1300     return(&xmlSecGCryptKeyDataRsaKlass);
1301 }
1302 
1303 /**
1304  * xmlSecGCryptKeyDataRsaAdoptKey:
1305  * @data:               the pointer to RSA key data.
1306  * @rsa_key:            the pointer to GCrypt RSA key.
1307  *
1308  * Sets the value of RSA key data.
1309  *
1310  * Returns: 0 on success or a negative value otherwise.
1311  */
1312 int
xmlSecGCryptKeyDataRsaAdoptKey(xmlSecKeyDataPtr data,gcry_sexp_t rsa_key)1313 xmlSecGCryptKeyDataRsaAdoptKey(xmlSecKeyDataPtr data, gcry_sexp_t rsa_key) {
1314     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
1315     xmlSecAssert2(rsa_key != NULL, -1);
1316 
1317     return xmlSecGCryptAsymKeyDataAdoptKey(data, rsa_key);
1318 }
1319 
1320 
1321 /**
1322  * xmlSecGCryptKeyDataRsaAdoptKeyPair:
1323  * @data:               the pointer to RSA key data.
1324  * @pub_key:            the pointer to GCrypt RSA pub key.
1325  * @priv_key:           the pointer to GCrypt RSA priv key.
1326  *
1327  * Sets the value of RSA key data.
1328  *
1329  * Returns: 0 on success or a negative value otherwise.
1330  */
1331 int
xmlSecGCryptKeyDataRsaAdoptKeyPair(xmlSecKeyDataPtr data,gcry_sexp_t pub_key,gcry_sexp_t priv_key)1332 xmlSecGCryptKeyDataRsaAdoptKeyPair(xmlSecKeyDataPtr data, gcry_sexp_t pub_key, gcry_sexp_t priv_key) {
1333     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
1334     xmlSecAssert2(pub_key != NULL, -1);
1335 
1336     return xmlSecGCryptAsymKeyDataAdoptKeyPair(data, pub_key, priv_key);
1337 }
1338 
1339 /**
1340  * xmlSecGCryptKeyDataRsaGetPublicKey:
1341  * @data:               the pointer to RSA key data.
1342  *
1343  * Gets the GCrypt RSA public key from RSA key data.
1344  *
1345  * Returns: pointer to GCrypt public RSA key or NULL if an error occurs.
1346  */
1347 gcry_sexp_t
xmlSecGCryptKeyDataRsaGetPublicKey(xmlSecKeyDataPtr data)1348 xmlSecGCryptKeyDataRsaGetPublicKey(xmlSecKeyDataPtr data) {
1349     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), NULL);
1350     return xmlSecGCryptAsymKeyDataGetPublicKey(data);
1351 }
1352 
1353 /**
1354  * xmlSecGCryptKeyDataRsaGetPrivateKey:
1355  * @data:               the pointer to RSA key data.
1356  *
1357  * Gets the GCrypt RSA private key from RSA key data.
1358  *
1359  * Returns: pointer to GCrypt private RSA key or NULL if an error occurs.
1360  */
1361 gcry_sexp_t
xmlSecGCryptKeyDataRsaGetPrivateKey(xmlSecKeyDataPtr data)1362 xmlSecGCryptKeyDataRsaGetPrivateKey(xmlSecKeyDataPtr data) {
1363     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), NULL);
1364     return xmlSecGCryptAsymKeyDataGetPrivateKey(data);
1365 }
1366 
1367 static int
xmlSecGCryptKeyDataRsaInitialize(xmlSecKeyDataPtr data)1368 xmlSecGCryptKeyDataRsaInitialize(xmlSecKeyDataPtr data) {
1369     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
1370 
1371     return(xmlSecGCryptAsymKeyDataInitialize(data));
1372 }
1373 
1374 static int
xmlSecGCryptKeyDataRsaDuplicate(xmlSecKeyDataPtr dst,xmlSecKeyDataPtr src)1375 xmlSecGCryptKeyDataRsaDuplicate(xmlSecKeyDataPtr dst, xmlSecKeyDataPtr src) {
1376     xmlSecAssert2(xmlSecKeyDataCheckId(dst, xmlSecGCryptKeyDataRsaId), -1);
1377     xmlSecAssert2(xmlSecKeyDataCheckId(src, xmlSecGCryptKeyDataRsaId), -1);
1378 
1379     return(xmlSecGCryptAsymKeyDataDuplicate(dst, src));
1380 }
1381 
1382 static void
xmlSecGCryptKeyDataRsaFinalize(xmlSecKeyDataPtr data)1383 xmlSecGCryptKeyDataRsaFinalize(xmlSecKeyDataPtr data) {
1384     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId));
1385 
1386     xmlSecGCryptAsymKeyDataFinalize(data);
1387 }
1388 
1389 static int
xmlSecGCryptKeyDataRsaGenerate(xmlSecKeyDataPtr data,xmlSecSize sizeBits,xmlSecKeyDataType type ATTRIBUTE_UNUSED)1390 xmlSecGCryptKeyDataRsaGenerate(xmlSecKeyDataPtr data, xmlSecSize sizeBits, xmlSecKeyDataType type ATTRIBUTE_UNUSED) {
1391     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), -1);
1392     xmlSecAssert2(sizeBits > 0, -1);
1393 
1394     return xmlSecGCryptAsymKeyDataGenerate(data, "rsa", sizeBits);
1395 }
1396 
1397 static xmlSecKeyDataType
xmlSecGCryptKeyDataRsaGetType(xmlSecKeyDataPtr data)1398 xmlSecGCryptKeyDataRsaGetType(xmlSecKeyDataPtr data) {
1399     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), xmlSecKeyDataTypeUnknown);
1400 
1401     return xmlSecGCryptAsymKeyDataGetType(data);
1402 }
1403 
1404 static xmlSecSize
xmlSecGCryptKeyDataRsaGetSize(xmlSecKeyDataPtr data)1405 xmlSecGCryptKeyDataRsaGetSize(xmlSecKeyDataPtr data) {
1406     xmlSecAssert2(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId), 0);
1407 
1408     return xmlSecGCryptAsymKeyDataGetSize(data);
1409 }
1410 
1411 static void
xmlSecGCryptKeyDataRsaDebugDump(xmlSecKeyDataPtr data,FILE * output)1412 xmlSecGCryptKeyDataRsaDebugDump(xmlSecKeyDataPtr data, FILE* output) {
1413     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId));
1414     xmlSecAssert(output != NULL);
1415 
1416     fprintf(output, "=== rsa key: size = %d\n",
1417             xmlSecGCryptKeyDataRsaGetSize(data));
1418 }
1419 
1420 static void
xmlSecGCryptKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data,FILE * output)1421 xmlSecGCryptKeyDataRsaDebugXmlDump(xmlSecKeyDataPtr data, FILE* output) {
1422     xmlSecAssert(xmlSecKeyDataCheckId(data, xmlSecGCryptKeyDataRsaId));
1423     xmlSecAssert(output != NULL);
1424 
1425     fprintf(output, "<RSAKeyValue size=\"%d\" />\n",
1426             xmlSecGCryptKeyDataRsaGetSize(data));
1427 }
1428 
1429 static int
xmlSecGCryptKeyDataRsaXmlRead(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1430 xmlSecGCryptKeyDataRsaXmlRead(xmlSecKeyDataId id, xmlSecKeyPtr key,
1431                                     xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1432     xmlNodePtr cur;
1433     xmlSecKeyDataPtr data = NULL;
1434     gcry_mpi_t n = NULL;
1435     gcry_mpi_t e = NULL;
1436     gcry_mpi_t d = NULL;
1437     gcry_sexp_t pub_key = NULL;
1438     gcry_sexp_t priv_key = NULL;
1439     gcry_error_t err;
1440     int res = -1;
1441     int ret;
1442 
1443     xmlSecAssert2(id == xmlSecGCryptKeyDataRsaId, -1);
1444     xmlSecAssert2(key != NULL, -1);
1445     xmlSecAssert2(node != NULL, -1);
1446     xmlSecAssert2(keyInfoCtx != NULL, -1);
1447 
1448     if(xmlSecKeyGetValue(key) != NULL) {
1449         xmlSecOtherError(XMLSEC_ERRORS_R_INVALID_KEY_DATA,
1450                          xmlSecKeyDataKlassGetName(id),
1451                          "key already has a value");
1452         goto done;
1453     }
1454 
1455     cur = xmlSecGetNextElementNode(node->children);
1456 
1457     /* first is Modulus node. It is REQUIRED */
1458     if((cur == NULL) || (!xmlSecCheckNodeName(cur,  xmlSecNodeRSAModulus, xmlSecDSigNs))) {
1459         xmlSecInvalidNodeError(cur, xmlSecNodeRSAModulus, xmlSecKeyDataKlassGetName(id));
1460         goto done;
1461     }
1462     n = xmlSecGCryptNodeGetMpiValue(cur);
1463     if(n == NULL) {
1464         xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeRSAModulus)",
1465                             xmlSecKeyDataKlassGetName(id));
1466         goto done;
1467     }
1468     cur = xmlSecGetNextElementNode(cur->next);
1469 
1470     /* next is Exponent node. It is REQUIRED */
1471     if((cur == NULL) || (!xmlSecCheckNodeName(cur, xmlSecNodeRSAExponent, xmlSecDSigNs))) {
1472         xmlSecInvalidNodeError(cur, xmlSecNodeRSAExponent, xmlSecKeyDataKlassGetName(id));
1473         goto done;
1474     }
1475     e = xmlSecGCryptNodeGetMpiValue(cur);
1476     if(e == NULL) {
1477         xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeRSAExponent)",
1478                             xmlSecKeyDataKlassGetName(id));
1479         goto done;
1480     }
1481     cur = xmlSecGetNextElementNode(cur->next);
1482 
1483     if((cur != NULL) && (xmlSecCheckNodeName(cur, xmlSecNodeRSAPrivateExponent, xmlSecNs))) {
1484         /* next is PrivateExponent node. It is REQUIRED for private key */
1485         d = xmlSecGCryptNodeGetMpiValue(cur);
1486         if(d == NULL) {
1487             xmlSecInternalError("xmlSecGCryptNodeGetMpiValue(NodeRSAPrivateExponent)",
1488                                 xmlSecKeyDataKlassGetName(id));
1489             goto done;
1490         }
1491         cur = xmlSecGetNextElementNode(cur->next);
1492     }
1493 
1494     if(cur != NULL) {
1495         xmlSecUnexpectedNodeError(cur, xmlSecKeyDataKlassGetName(id));
1496         goto done;
1497     }
1498 
1499     /* construct pub/priv key pairs */
1500     err = gcry_sexp_build(&pub_key, NULL,
1501              "(public-key(rsa(n%m)(e%m)))",
1502              n, e);
1503     if((err != GPG_ERR_NO_ERROR) || (pub_key == NULL)) {
1504         xmlSecGCryptError("gcry_sexp_build(public)", err,
1505                           xmlSecKeyDataGetName(data));
1506         goto done;
1507     }
1508     if(d != NULL) {
1509         err = gcry_sexp_build(&priv_key, NULL,
1510                  "(private-key(rsa(n%m)(e%m)(d%m)))",
1511                  n, e, d);
1512         if((err != GPG_ERR_NO_ERROR) || (priv_key == NULL)) {
1513             xmlSecGCryptError("gcry_sexp_build(private)", err,
1514                               xmlSecKeyDataGetName(data));
1515             goto done;
1516         }
1517     }
1518 
1519 
1520     /* create key data */
1521     data = xmlSecKeyDataCreate(id);
1522     if(data == NULL ) {
1523         xmlSecInternalError("xmlSecKeyDataCreate",
1524                             xmlSecKeyDataKlassGetName(id));
1525         goto done;
1526     }
1527 
1528     ret = xmlSecGCryptKeyDataRsaAdoptKeyPair(data, pub_key, priv_key);
1529     if(ret < 0) {
1530         xmlSecInternalError("xmlSecGCryptKeyDataRsaAdoptKeyPair",
1531                             xmlSecKeyDataGetName(data));
1532         goto done;
1533     }
1534     pub_key = NULL; /* pub_key is owned by data now */
1535     priv_key = NULL; /* priv_key is owned by data now */
1536 
1537     /* set key */
1538     ret = xmlSecKeySetValue(key, data);
1539     if(ret < 0) {
1540         xmlSecInternalError("xmlSecKeySetValue",
1541                             xmlSecKeyDataGetName(data));
1542         goto done;
1543     }
1544     data = NULL; /* data is owned by key now */
1545 
1546 
1547     /* success */
1548     res = 0;
1549 
1550 done:
1551     /* cleanup */
1552     if(n != NULL) {
1553         gcry_mpi_release(n);
1554     }
1555 
1556     if(e != NULL) {
1557         gcry_mpi_release(e);
1558     }
1559 
1560     if(d != NULL) {
1561         gcry_mpi_release(d);
1562     }
1563 
1564     if(pub_key != NULL) {
1565         gcry_sexp_release(pub_key);
1566     }
1567 
1568     if(priv_key != NULL) {
1569         gcry_sexp_release(priv_key);
1570     }
1571 
1572     if(data != NULL) {
1573         xmlSecKeyDataDestroy(data);
1574     }
1575     return(res);
1576 
1577 }
1578 
1579 static int
xmlSecGCryptKeyDataRsaXmlWrite(xmlSecKeyDataId id,xmlSecKeyPtr key,xmlNodePtr node,xmlSecKeyInfoCtxPtr keyInfoCtx)1580 xmlSecGCryptKeyDataRsaXmlWrite(xmlSecKeyDataId id, xmlSecKeyPtr key,
1581                             xmlNodePtr node, xmlSecKeyInfoCtxPtr keyInfoCtx) {
1582     xmlNodePtr cur;
1583     gcry_sexp_t pub_priv_key;
1584     gcry_sexp_t rsa = NULL;
1585     int private = 0;
1586     int res = -1;
1587     int ret;
1588 
1589     xmlSecAssert2(id == xmlSecGCryptKeyDataRsaId, -1);
1590     xmlSecAssert2(key != NULL, -1);
1591     xmlSecAssert2(xmlSecKeyDataCheckId(xmlSecKeyGetValue(key), xmlSecGCryptKeyDataRsaId), -1);
1592     xmlSecAssert2(node != NULL, -1);
1593     xmlSecAssert2(keyInfoCtx != NULL, -1);
1594 
1595     if(((xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate) & keyInfoCtx->keyReq.keyType) == 0) {
1596         /* we can have only private key or public key */
1597         return(0);
1598     }
1599 
1600     /* find the private or public key */
1601     pub_priv_key = xmlSecGCryptKeyDataRsaGetPrivateKey(xmlSecKeyGetValue(key));
1602     if(pub_priv_key == NULL) {
1603         pub_priv_key = xmlSecGCryptKeyDataRsaGetPublicKey(xmlSecKeyGetValue(key));
1604         if(pub_priv_key == NULL) {
1605             xmlSecInternalError("xmlSecGCryptKeyDataRsaGetPublicKey()",
1606                                 xmlSecKeyDataKlassGetName(id));
1607             goto done;
1608         }
1609     } else {
1610         private = 1;
1611     }
1612 
1613     rsa = gcry_sexp_find_token(pub_priv_key, "rsa", 0);
1614     if(rsa == NULL) {
1615         xmlSecGCryptError("gcry_sexp_find_token(rsa)",
1616                           GPG_ERR_NO_ERROR,
1617                           xmlSecKeyDataKlassGetName(id));
1618         goto done;
1619     }
1620 
1621     /* first is Modulus node */
1622     cur = xmlSecAddChild(node, xmlSecNodeRSAModulus, xmlSecDSigNs);
1623     if(cur == NULL) {
1624         xmlSecInternalError("xmlSecAddChild(NodeRSAModulus)",
1625                             xmlSecKeyDataKlassGetName(id));
1626        goto done;
1627     }
1628     ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "n", 1);
1629     if(ret < 0) {
1630         xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeRSAModulus)",
1631                             xmlSecKeyDataKlassGetName(id));
1632         goto done;
1633     }
1634 
1635     /* next is Exponent node. */
1636     cur = xmlSecAddChild(node, xmlSecNodeRSAExponent, xmlSecDSigNs);
1637     if(cur == NULL) {
1638         xmlSecInternalError("xmlSecAddChild(NodeRSAExponent)",
1639                             xmlSecKeyDataKlassGetName(id));
1640        goto done;
1641     }
1642     ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "e", 1);
1643     if(ret < 0) {
1644         xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeRSAExponent)",
1645                             xmlSecKeyDataKlassGetName(id));
1646        goto done;
1647     }
1648 
1649     /* next is PrivateExponent node: write it ONLY for private keys and ONLY if it is requested */
1650     if(((keyInfoCtx->keyReq.keyType & xmlSecKeyDataTypePrivate) != 0) && (private != 0)) {
1651         cur = xmlSecAddChild(node, xmlSecNodeRSAPrivateExponent, xmlSecNs);
1652         if(cur == NULL) {
1653             xmlSecInternalError("xmlSecAddChild(NodeRSAPrivateExponent)",
1654                                 xmlSecKeyDataKlassGetName(id));
1655            goto done;
1656         }
1657         ret = xmlSecGCryptNodeSetSExpTokValue(cur, rsa, "d", 1);
1658         if(ret < 0) {
1659             xmlSecInternalError("xmlSecGCryptNodeSetSExpTokValue(NodeRSAPrivateExponent)",
1660                                 xmlSecKeyDataKlassGetName(id));
1661            goto done;
1662         }
1663     }
1664 
1665     /* success */
1666     res = 0;
1667 
1668 done:
1669     if(rsa != NULL) {
1670         gcry_sexp_release(rsa);
1671     }
1672 
1673     return(res);
1674 }
1675 
1676 #endif /* XMLSEC_NO_RSA */
1677