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