Line data Source code
1 : /* keyinfo.c - Parse and build a keyInfo structure
2 : * Copyright (C) 2001, 2002, 2007, 2008, 2012 g10 Code GmbH
3 : *
4 : * This file is part of KSBA.
5 : *
6 : * KSBA is free software; you can redistribute it and/or modify
7 : * it under the terms of either
8 : *
9 : * - the GNU Lesser General Public License as published by the Free
10 : * Software Foundation; either version 3 of the License, or (at
11 : * your option) any later version.
12 : *
13 : * or
14 : *
15 : * - the GNU General Public License as published by the Free
16 : * Software Foundation; either version 2 of the License, or (at
17 : * your option) any later version.
18 : *
19 : * or both in parallel, as here.
20 : *
21 : * KSBA is distributed in the hope that it will be useful, but WITHOUT
22 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 : * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
24 : * License for more details.
25 : *
26 : * You should have received a copies of the GNU General Public License
27 : * and the GNU Lesser General Public License along with this program;
28 : * if not, see <http://www.gnu.org/licenses/>.
29 : */
30 :
31 : /* Instead of using the ASN parser - which is easily possible - we use
32 : a simple handcoded one to speed up the operation and to make it
33 : more robust. */
34 :
35 : #include <config.h>
36 : #include <stdio.h>
37 : #include <stdlib.h>
38 : #include <string.h>
39 : #include <assert.h>
40 :
41 : #include "util.h"
42 : #include "asn1-func.h"
43 : #include "keyinfo.h"
44 : #include "shared.h"
45 : #include "convert.h"
46 : #include "ber-help.h"
47 :
48 :
49 : /* Constants used for the public key algorithms. */
50 : typedef enum
51 : {
52 : PKALGO_RSA,
53 : PKALGO_DSA,
54 : PKALGO_ECC
55 : }
56 : pkalgo_t;
57 :
58 :
59 : struct algo_table_s {
60 : const char *oidstring;
61 : const unsigned char *oid; /* NULL indicattes end of table */
62 : int oidlen;
63 : int supported;
64 : pkalgo_t pkalgo;
65 : const char *algo_string;
66 : const char *elem_string; /* parameter name or '-' */
67 : const char *ctrl_string; /* expected tag values (value > 127 are raw data)*/
68 : const char *parmelem_string; /* parameter name or '-'. */
69 : const char *parmctrl_string; /* expected tag values. */
70 : const char *digest_string; /* The digest algo if included in the OID. */
71 : };
72 :
73 :
74 :
75 : static const struct algo_table_s pk_algo_table[] = {
76 :
77 : { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
78 : "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */
79 : "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01", 9,
80 : 1, PKALGO_RSA, "rsa", "-ne", "\x30\x02\x02" },
81 :
82 : { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.7 */
83 : "1.2.840.113549.1.1.7", /* RSAES-OAEP */
84 : "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x07", 9,
85 : 0, PKALGO_RSA, "rsa", "-ne", "\x30\x02\x02"}, /* (patent problems) */
86 :
87 : { /* */
88 : "2.5.8.1.1", /* rsa (ambiguous due to missing padding rules)*/
89 : "\x55\x08\x01\x01", 4,
90 : 1, PKALGO_RSA, "ambiguous-rsa", "-ne", "\x30\x02\x02" },
91 :
92 : { /* iso.member-body.us.x9-57.x9cm.1 */
93 : "1.2.840.10040.4.1", /* dsa */
94 : "\x2a\x86\x48\xce\x38\x04\x01", 7,
95 : 1, PKALGO_DSA, "dsa", "y", "\x02", "-pqg", "\x30\x02\x02\x02" },
96 :
97 : { /* iso.member-body.us.ansi-x9-62.2.1 */
98 : "1.2.840.10045.2.1", /* ecPublicKey */
99 : "\x2a\x86\x48\xce\x3d\x02\x01", 7,
100 : 1, PKALGO_ECC, "ecc", "q", "\x80" },
101 :
102 : {NULL}
103 : };
104 :
105 :
106 : static const struct algo_table_s sig_algo_table[] = {
107 : { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.5 */
108 : "1.2.840.113549.1.1.5", /* sha1WithRSAEncryption */
109 : "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05", 9,
110 : 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha1" },
111 : { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.4 */
112 : "1.2.840.113549.1.1.4", /* md5WithRSAEncryption */
113 : "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04", 9,
114 : 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "md5" },
115 : { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.2 */
116 : "1.2.840.113549.1.1.2", /* md2WithRSAEncryption */
117 : "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02", 9,
118 : 0, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "md2" },
119 : { /* iso.member-body.us.x9-57.x9cm.1 */
120 : "1.2.840.10040.4.3", /* dsa */
121 : "\x2a\x86\x48\xce\x38\x04\x01", 7,
122 : 1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02" },
123 : { /* iso.member-body.us.x9-57.x9cm.3 */
124 : "1.2.840.10040.4.3", /* dsaWithSha1 */
125 : "\x2a\x86\x48\xce\x38\x04\x03", 7,
126 : 1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha1" },
127 : { /* Teletrust signature algorithm. */
128 : "1.3.36.8.5.1.2.2", /* dsaWithRIPEMD160 */
129 : "\x2b\x24\x08\x05\x01\x02\x02", 7,
130 : 1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "rmd160" },
131 : { /* NIST Algorithm */
132 : "2.16.840.1.101.3.4.3.1", /* dsaWithSha224 */
133 : "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x03\x01", 11,
134 : 1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha224" },
135 : { /* NIST Algorithm (the draft also used .1 but we better use .2) */
136 : "2.16.840.1.101.3.4.3.2", /* dsaWithSha256 */
137 : "\x06\x09\x60\x86\x48\x01\x65\x03\x04\x03\x01", 11,
138 : 1, PKALGO_DSA, "dsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha256" },
139 :
140 : { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha1 */
141 : "1.2.840.10045.4.1", /* ecdsa */
142 : "\x2a\x86\x48\xce\x3d\x04\x01", 7,
143 : 1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha1" },
144 :
145 : { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-specified */
146 : "1.2.840.10045.4.3",
147 : "\x2a\x86\x48\xce\x3d\x04\x03", 7,
148 : 1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, NULL },
149 : /* The digest algorithm is given by the parameter. */
150 :
151 :
152 : { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha224 */
153 : "1.2.840.10045.4.3.1",
154 : "\x2a\x86\x48\xce\x3d\x04\x03\x01", 8,
155 : 1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha224" },
156 :
157 : { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha256 */
158 : "1.2.840.10045.4.3.2",
159 : "\x2a\x86\x48\xce\x3d\x04\x03\x02", 8,
160 : 1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha256" },
161 :
162 : { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha384 */
163 : "1.2.840.10045.4.3.3",
164 : "\x2a\x86\x48\xce\x3d\x04\x03\x03", 8,
165 : 1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha384" },
166 :
167 : { /* iso.member-body.us.ansi-x9-62.signatures.ecdsa-with-sha512 */
168 : "1.2.840.10045.4.3.4",
169 : "\x2a\x86\x48\xce\x3d\x04\x03\x04", 8,
170 : 1, PKALGO_ECC, "ecdsa", "-rs", "\x30\x02\x02", NULL, NULL, "sha512" },
171 :
172 : { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
173 : "1.2.840.113549.1.1.1", /* rsaEncryption used without hash algo*/
174 : "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01", 9,
175 : 1, PKALGO_RSA, "rsa", "s", "\x82" },
176 : { /* from NIST's OIW - actually belongs in a pure hash table */
177 : "1.3.14.3.2.26", /* sha1 */
178 : "\x2B\x0E\x03\x02\x1A", 5,
179 : 0, PKALGO_RSA, "sha-1", "", "", NULL, NULL, "sha1" },
180 :
181 : { /* As used by telesec cards */
182 : "1.3.36.3.3.1.2", /* rsaSignatureWithripemd160 */
183 : "\x2b\x24\x03\x03\x01\x02", 6,
184 : 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "rmd160" },
185 :
186 : { /* from NIST's OIW - used by TU Darmstadt */
187 : "1.3.14.3.2.29", /* sha-1WithRSAEncryption */
188 : "\x2B\x0E\x03\x02\x1D", 5,
189 : 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha1" },
190 :
191 : { /* from PKCS#1 */
192 : "1.2.840.113549.1.1.11", /* sha256WithRSAEncryption */
193 : "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b", 9,
194 : 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha256" },
195 :
196 : { /* from PKCS#1 */
197 : "1.2.840.113549.1.1.12", /* sha384WithRSAEncryption */
198 : "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0c", 9,
199 : 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha384" },
200 :
201 : { /* from PKCS#1 */
202 : "1.2.840.113549.1.1.13", /* sha512WithRSAEncryption */
203 : "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0d", 9,
204 : 1, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "sha512" },
205 :
206 : { /* TeleTrust signature scheme with RSA signature and DSI according
207 : to ISO/IEC 9796-2 with random number and RIPEMD-160. I am not
208 : sure for what this is good; thus disabled. */
209 : "1.3.36.3.4.3.2.2", /* sigS_ISO9796-2rndWithrsa_ripemd160 */
210 : "\x2B\x24\x03\x04\x03\x02\x02", 7,
211 : 0, PKALGO_RSA, "rsa", "s", "\x82", NULL, NULL, "rmd160" },
212 :
213 : {NULL}
214 : };
215 :
216 : static const struct algo_table_s enc_algo_table[] = {
217 : { /* iso.member-body.us.rsadsi.pkcs.pkcs-1.1 */
218 : "1.2.840.113549.1.1.1", /* rsaEncryption (RSAES-PKCA1-v1.5) */
219 : "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", 9,
220 : 1, PKALGO_RSA, "rsa", "a", "\x82" },
221 : {NULL}
222 : };
223 :
224 :
225 : /* This tables maps names of ECC curves names to OIDs. A similar
226 : table is used by lib gcrypt. */
227 : static const struct
228 : {
229 : const char *oid;
230 : const char *name;
231 : } curve_names[] =
232 : {
233 : { "1.3.6.1.4.1.3029.1.5.1", "Curve25519" },
234 : { "1.3.6.1.4.1.11591.15.1", "Ed25519" },
235 :
236 : { "1.2.840.10045.3.1.1", "NIST P-192" },
237 : { "1.2.840.10045.3.1.1", "nistp192" },
238 : { "1.2.840.10045.3.1.1", "prime192v1" },
239 : { "1.2.840.10045.3.1.1", "secp192r1" },
240 :
241 : { "1.3.132.0.33", "NIST P-224" },
242 : { "1.3.132.0.33", "nistp224" },
243 : { "1.3.132.0.33", "secp224r1" },
244 :
245 : { "1.2.840.10045.3.1.7", "NIST P-256" },
246 : { "1.2.840.10045.3.1.7", "nistp256" },
247 : { "1.2.840.10045.3.1.7", "prime256v1" },
248 : { "1.2.840.10045.3.1.7", "secp256r1" },
249 :
250 : { "1.3.132.0.34", "NIST P-384" },
251 : { "1.3.132.0.34", "nistp384" },
252 : { "1.3.132.0.34", "secp384r1" },
253 :
254 : { "1.3.132.0.35", "NIST P-521" },
255 : { "1.3.132.0.35", "nistp521" },
256 : { "1.3.132.0.35", "secp521r1" },
257 :
258 : { "1.3.36.3.3.2.8.1.1.1" , "brainpoolP160r1" },
259 : { "1.3.36.3.3.2.8.1.1.3" , "brainpoolP192r1" },
260 : { "1.3.36.3.3.2.8.1.1.5" , "brainpoolP224r1" },
261 : { "1.3.36.3.3.2.8.1.1.7" , "brainpoolP256r1" },
262 : { "1.3.36.3.3.2.8.1.1.9" , "brainpoolP320r1" },
263 : { "1.3.36.3.3.2.8.1.1.11", "brainpoolP384r1" },
264 : { "1.3.36.3.3.2.8.1.1.13", "brainpoolP512r1" },
265 :
266 :
267 : { "1.2.643.2.2.35.1", "GOST2001-CryptoPro-A" },
268 : { "1.2.643.2.2.35.2", "GOST2001-CryptoPro-B" },
269 : { "1.2.643.2.2.35.3", "GOST2001-CryptoPro-C" },
270 : { "1.2.643.7.1.2.1.2.1", "GOST2012-tc26-A" },
271 : { "1.2.643.7.1.2.1.2.2", "GOST2012-tc26-B" },
272 :
273 : { "1.3.132.0.10", "secp256k1" },
274 :
275 : { NULL, NULL}
276 : };
277 :
278 :
279 :
280 :
281 :
282 : struct stringbuf {
283 : size_t len;
284 : size_t size;
285 : char *buf;
286 : int out_of_core;
287 : };
288 :
289 :
290 : #define TLV_LENGTH(prefix) do { \
291 : if (!prefix ## len) \
292 : return gpg_error (GPG_ERR_INV_KEYINFO); \
293 : c = *(prefix)++; prefix ## len--; \
294 : if (c == 0x80) \
295 : return gpg_error (GPG_ERR_NOT_DER_ENCODED); \
296 : if (c == 0xff) \
297 : return gpg_error (GPG_ERR_BAD_BER); \
298 : \
299 : if ( !(c & 0x80) ) \
300 : len = c; \
301 : else \
302 : { \
303 : int count = c & 0x7f; \
304 : \
305 : for (len=0; count; count--) \
306 : { \
307 : len <<= 8; \
308 : if (!prefix ## len) \
309 : return gpg_error (GPG_ERR_BAD_BER);\
310 : c = *(prefix)++; prefix ## len--; \
311 : len |= c & 0xff; \
312 : } \
313 : } \
314 : if (len > prefix ## len) \
315 : return gpg_error (GPG_ERR_INV_KEYINFO); \
316 : } while (0)
317 :
318 :
319 : /* Given a string BUF of length BUFLEN with either the name of an ECC
320 : curve or its OID in dotted form return the DER encoding of the OID.
321 : The caller must free the result. On error NULL is returned. */
322 : static unsigned char *
323 0 : get_ecc_curve_oid (const unsigned char *buf, size_t buflen, size_t *r_oidlen)
324 : {
325 : unsigned char *der_oid;
326 :
327 : /* Skip an optional "oid." prefix. */
328 0 : if (buflen > 4 && buf[3] == '.' && digitp (buf+4)
329 0 : && ((buf[0] == 'o' && buf[1] == 'i' && buf[2] == 'd')
330 0 : ||(buf[0] == 'O' && buf[1] == 'I' && buf[2] == 'D')))
331 : {
332 0 : buf += 4;
333 0 : buflen -= 4;
334 : }
335 :
336 : /* If it does not look like an OID - map it through the table. */
337 0 : if (buflen && !digitp (buf))
338 : {
339 : int i;
340 :
341 0 : for (i=0; curve_names[i].oid; i++)
342 0 : if (buflen == strlen (curve_names[i].name)
343 0 : && !memcmp (buf, curve_names[i].name, buflen))
344 0 : break;
345 0 : if (!curve_names[i].oid)
346 0 : return NULL; /* Not found. */
347 0 : buf = curve_names[i].oid;
348 0 : buflen = strlen (curve_names[i].oid);
349 : }
350 :
351 0 : if (_ksba_oid_from_buf (buf, buflen, &der_oid, r_oidlen))
352 0 : return NULL;
353 0 : return der_oid;
354 : }
355 :
356 :
357 :
358 : /* Return the OFF and the LEN of algorithm within DER. Do some checks
359 : and return the number of bytes read in r_nread, adding this to der
360 : does point into the BIT STRING.
361 :
362 : mode 0: just get the algorithm identifier. FIXME: should be able to
363 : handle BER Encoding.
364 : mode 1: as described.
365 : */
366 : static gpg_error_t
367 11 : get_algorithm (int mode, const unsigned char *der, size_t derlen,
368 : size_t *r_nread, size_t *r_pos, size_t *r_len, int *r_bitstr,
369 : size_t *r_parm_pos, size_t *r_parm_len, int *r_parm_type)
370 : {
371 : int c;
372 11 : const unsigned char *start = der;
373 : const unsigned char *startseq;
374 : unsigned long seqlen, len;
375 :
376 11 : *r_bitstr = 0;
377 11 : if (r_parm_pos)
378 10 : *r_parm_pos = 0;
379 11 : if (r_parm_len)
380 10 : *r_parm_len = 0;
381 11 : if (r_parm_type)
382 10 : *r_parm_type = 0;
383 : /* get the inner sequence */
384 11 : if (!derlen)
385 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
386 11 : c = *der++; derlen--;
387 11 : if ( c != 0x30 )
388 0 : return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */
389 11 : TLV_LENGTH(der);
390 11 : seqlen = len;
391 11 : startseq = der;
392 :
393 : /* get the object identifier */
394 11 : if (!derlen)
395 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
396 11 : c = *der++; derlen--;
397 11 : if ( c != 0x06 )
398 0 : return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not an OBJECT IDENTIFIER */
399 11 : TLV_LENGTH(der);
400 :
401 : /* der does now point to an oid of length LEN */
402 11 : *r_pos = der - start;
403 11 : *r_len = len;
404 : /* { */
405 : /* char *p = ksba_oid_to_str (der, len); */
406 : /* printf ("algorithm: %s\n", p); */
407 : /* xfree (p); */
408 : /* } */
409 11 : der += len;
410 11 : derlen -= len;
411 11 : seqlen -= der - startseq;;
412 :
413 : /* Parse the parameter. */
414 11 : if (seqlen)
415 : {
416 11 : const unsigned char *startparm = der;
417 :
418 11 : if (!derlen)
419 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
420 11 : c = *der++; derlen--;
421 11 : if ( c == 0x05 )
422 : {
423 : /*printf ("parameter: NULL \n"); the usual case */
424 11 : if (!derlen)
425 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
426 11 : c = *der++; derlen--;
427 11 : if (c)
428 0 : return gpg_error (GPG_ERR_BAD_BER); /* NULL must have a
429 : length of 0 */
430 11 : seqlen -= 2;
431 : }
432 0 : else if (r_parm_pos && r_parm_len && c == 0x04)
433 : {
434 : /* This is an octet string parameter and we need it. */
435 0 : if (r_parm_type)
436 0 : *r_parm_type = TYPE_OCTET_STRING;
437 0 : TLV_LENGTH(der);
438 0 : *r_parm_pos = der - start;
439 0 : *r_parm_len = len;
440 0 : seqlen -= der - startparm;
441 0 : der += len;
442 0 : derlen -= len;
443 0 : seqlen -= len;
444 : }
445 0 : else if (r_parm_pos && r_parm_len && c == 0x06)
446 : {
447 : /* This is an object identifier. */
448 0 : if (r_parm_type)
449 0 : *r_parm_type = TYPE_OBJECT_ID;
450 0 : TLV_LENGTH(der);
451 0 : *r_parm_pos = der - start;
452 0 : *r_parm_len = len;
453 0 : seqlen -= der - startparm;
454 0 : der += len;
455 0 : derlen -= len;
456 0 : seqlen -= len;
457 : }
458 0 : else if (r_parm_pos && r_parm_len && c == 0x30)
459 : {
460 : /* This is a sequence. */
461 0 : if (r_parm_type)
462 0 : *r_parm_type = TYPE_SEQUENCE;
463 0 : TLV_LENGTH(der);
464 0 : *r_parm_pos = startparm - start;
465 0 : *r_parm_len = len + (der - startparm);
466 0 : seqlen -= der - startparm;
467 0 : der += len;
468 0 : derlen -= len;
469 0 : seqlen -= len;
470 : }
471 : else
472 : {
473 : /* printf ("parameter: with tag %02x - ignored\n", c); */
474 0 : TLV_LENGTH(der);
475 0 : seqlen -= der - startparm;
476 : /* skip the value */
477 0 : der += len;
478 0 : derlen -= len;
479 0 : seqlen -= len;
480 : }
481 : }
482 :
483 11 : if (seqlen)
484 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
485 :
486 11 : if (mode)
487 : {
488 : /* move forward to the BIT_STR */
489 7 : if (!derlen)
490 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
491 7 : c = *der++; derlen--;
492 :
493 7 : if (c == 0x03)
494 7 : *r_bitstr = 1; /* BIT STRING */
495 0 : else if (c == 0x04)
496 : ; /* OCTECT STRING */
497 : else
498 0 : return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a BIT STRING */
499 7 : TLV_LENGTH(der);
500 : }
501 :
502 11 : *r_nread = der - start;
503 11 : return 0;
504 : }
505 :
506 :
507 : gpg_error_t
508 3 : _ksba_parse_algorithm_identifier (const unsigned char *der, size_t derlen,
509 : size_t *r_nread, char **r_oid)
510 : {
511 3 : return _ksba_parse_algorithm_identifier2 (der, derlen,
512 : r_nread, r_oid, NULL, NULL);
513 : }
514 :
515 : gpg_error_t
516 4 : _ksba_parse_algorithm_identifier2 (const unsigned char *der, size_t derlen,
517 : size_t *r_nread, char **r_oid,
518 : char **r_parm, size_t *r_parmlen)
519 : {
520 : gpg_error_t err;
521 : int is_bitstr;
522 : size_t nread, off, len, off2, len2;
523 : int parm_type;
524 :
525 : /* fixme: get_algorithm might return the error invalid keyinfo -
526 : this should be invalid algorithm identifier */
527 4 : *r_oid = NULL;
528 4 : *r_nread = 0;
529 4 : off2 = len2 = 0;
530 4 : err = get_algorithm (0, der, derlen, &nread, &off, &len, &is_bitstr,
531 : &off2, &len2, &parm_type);
532 4 : if (err)
533 0 : return err;
534 4 : *r_nread = nread;
535 4 : *r_oid = ksba_oid_to_str (der+off, len);
536 4 : if (!*r_oid)
537 0 : return gpg_error (GPG_ERR_ENOMEM);
538 :
539 : /* Special hack for ecdsaWithSpecified. We replace the returned OID
540 : by the one in the parameter. */
541 4 : if (off2 && len2 && parm_type == TYPE_SEQUENCE
542 0 : && !strcmp (*r_oid, "1.2.840.10045.4.3"))
543 : {
544 0 : xfree (*r_oid);
545 0 : *r_oid = NULL;
546 0 : err = get_algorithm (0, der+off2, len2, &nread, &off, &len, &is_bitstr,
547 : NULL, NULL, NULL);
548 0 : if (err)
549 : {
550 0 : *r_nread = 0;
551 0 : return err;
552 : }
553 0 : *r_oid = ksba_oid_to_str (der+off2+off, len);
554 0 : if (!*r_oid)
555 : {
556 0 : *r_nread = 0;
557 0 : return gpg_error (GPG_ERR_ENOMEM);
558 : }
559 :
560 0 : off2 = len2 = 0; /* So that R_PARM is set to NULL. */
561 : }
562 :
563 4 : if (r_parm && r_parmlen)
564 : {
565 1 : if (off2 && len2)
566 : {
567 0 : *r_parm = xtrymalloc (len2);
568 0 : if (!*r_parm)
569 : {
570 0 : xfree (*r_oid);
571 0 : *r_oid = NULL;
572 0 : return gpg_error (GPG_ERR_ENOMEM);
573 : }
574 0 : memcpy (*r_parm, der+off2, len2);
575 0 : *r_parmlen = len2;
576 : }
577 : else
578 : {
579 1 : *r_parm = NULL;
580 1 : *r_parmlen = 0;
581 : }
582 : }
583 4 : return 0;
584 : }
585 :
586 :
587 :
588 : static void
589 7 : init_stringbuf (struct stringbuf *sb, int initiallen)
590 : {
591 7 : sb->len = 0;
592 7 : sb->size = initiallen;
593 7 : sb->out_of_core = 0;
594 : /* allocate one more, so that get_stringbuf can append a nul */
595 7 : sb->buf = xtrymalloc (initiallen+1);
596 7 : if (!sb->buf)
597 0 : sb->out_of_core = 1;
598 7 : }
599 :
600 : static void
601 111 : put_stringbuf_mem (struct stringbuf *sb, const char *text, size_t n)
602 : {
603 111 : if (sb->out_of_core)
604 0 : return;
605 :
606 111 : if (sb->len + n >= sb->size)
607 : {
608 : char *p;
609 :
610 7 : sb->size += n + 100;
611 7 : p = xtryrealloc (sb->buf, sb->size);
612 7 : if ( !p)
613 : {
614 0 : sb->out_of_core = 1;
615 0 : return;
616 : }
617 7 : sb->buf = p;
618 : }
619 111 : memcpy (sb->buf+sb->len, text, n);
620 111 : sb->len += n;
621 : }
622 :
623 : static void
624 77 : put_stringbuf (struct stringbuf *sb, const char *text)
625 : {
626 77 : put_stringbuf_mem (sb, text,strlen (text));
627 77 : }
628 :
629 : static void
630 34 : put_stringbuf_mem_sexp (struct stringbuf *sb, const char *text, size_t length)
631 : {
632 : char buf[20];
633 34 : sprintf (buf,"%u:", (unsigned int)length);
634 34 : put_stringbuf (sb, buf);
635 34 : put_stringbuf_mem (sb, text, length);
636 34 : }
637 :
638 : static void
639 21 : put_stringbuf_sexp (struct stringbuf *sb, const char *text)
640 : {
641 21 : put_stringbuf_mem_sexp (sb, text, strlen (text));
642 21 : }
643 :
644 :
645 : static char *
646 7 : get_stringbuf (struct stringbuf *sb)
647 : {
648 : char *p;
649 :
650 7 : if (sb->out_of_core)
651 : {
652 0 : xfree (sb->buf); sb->buf = NULL;
653 0 : return NULL;
654 : }
655 :
656 7 : sb->buf[sb->len] = 0;
657 7 : p = sb->buf;
658 7 : sb->buf = NULL;
659 7 : sb->out_of_core = 1; /* make sure the caller does an init before reuse */
660 7 : return p;
661 : }
662 :
663 :
664 : /* Assume that der is a buffer of length DERLEN with a DER encoded
665 : Asn.1 structure like this:
666 :
667 : keyInfo ::= SEQUENCE {
668 : SEQUENCE {
669 : algorithm OBJECT IDENTIFIER,
670 : parameters ANY DEFINED BY algorithm OPTIONAL }
671 : publicKey BIT STRING }
672 :
673 : The function parses this structure and create a SEXP suitable to be
674 : used as a public key in Libgcrypt. The S-Exp will be returned in a
675 : string which the caller must free.
676 :
677 : We don't pass an ASN.1 node here but a plain memory block. */
678 :
679 : gpg_error_t
680 6 : _ksba_keyinfo_to_sexp (const unsigned char *der, size_t derlen,
681 : ksba_sexp_t *r_string)
682 : {
683 : gpg_error_t err;
684 : int c;
685 : size_t nread, off, len, parm_off, parm_len;
686 : int parm_type;
687 6 : char *parm_oid = NULL;
688 : int algoidx;
689 : int is_bitstr;
690 6 : const unsigned char *parmder = NULL;
691 6 : size_t parmderlen = 0;
692 : const unsigned char *ctrl;
693 : const char *elem;
694 : struct stringbuf sb;
695 :
696 6 : *r_string = NULL;
697 :
698 : /* check the outer sequence */
699 6 : if (!derlen)
700 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
701 6 : c = *der++; derlen--;
702 6 : if ( c != 0x30 )
703 0 : return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */
704 6 : TLV_LENGTH(der);
705 : /* and now the inner part */
706 6 : err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
707 : &parm_off, &parm_len, &parm_type);
708 6 : if (err)
709 0 : return err;
710 :
711 : /* look into our table of supported algorithms */
712 6 : for (algoidx=0; pk_algo_table[algoidx].oid; algoidx++)
713 : {
714 6 : if ( len == pk_algo_table[algoidx].oidlen
715 6 : && !memcmp (der+off, pk_algo_table[algoidx].oid, len))
716 6 : break;
717 : }
718 6 : if (!pk_algo_table[algoidx].oid)
719 0 : return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
720 6 : if (!pk_algo_table[algoidx].supported)
721 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
722 :
723 6 : if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID)
724 0 : parm_oid = ksba_oid_to_str (der+parm_off, parm_len);
725 6 : else if (parm_off && parm_len)
726 : {
727 0 : parmder = der + parm_off;
728 0 : parmderlen = parm_len;
729 : }
730 :
731 6 : der += nread;
732 6 : derlen -= nread;
733 :
734 6 : if (is_bitstr)
735 : { /* Funny: X.509 defines the signature value as a bit string but
736 : CMS as an octet string - for ease of implementation we always
737 : allow both */
738 6 : if (!derlen)
739 : {
740 0 : xfree (parm_oid);
741 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
742 : }
743 6 : c = *der++; derlen--;
744 6 : if (c)
745 0 : fprintf (stderr, "warning: number of unused bits is not zero\n");
746 : }
747 :
748 : /* fixme: we should calculate the initial length form the size of the
749 : sequence, so that we don't need a realloc later */
750 6 : init_stringbuf (&sb, 100);
751 6 : put_stringbuf (&sb, "(10:public-key(");
752 :
753 : /* fixme: we can also use the oidstring here and prefix it with
754 : "oid." - this way we can pass more information into Libgcrypt or
755 : whatever library is used */
756 6 : put_stringbuf_sexp (&sb, pk_algo_table[algoidx].algo_string);
757 :
758 : /* Insert the curve name for ECC. */
759 6 : if (pk_algo_table[algoidx].pkalgo == PKALGO_ECC && parm_oid)
760 : {
761 0 : put_stringbuf (&sb, "(");
762 0 : put_stringbuf_sexp (&sb, "curve");
763 0 : put_stringbuf_sexp (&sb, parm_oid);
764 0 : put_stringbuf (&sb, ")");
765 : }
766 :
767 : /* If parameters are given and we have a description for them, parse
768 : them. */
769 6 : if (parmder && parmderlen
770 0 : && pk_algo_table[algoidx].parmelem_string
771 0 : && pk_algo_table[algoidx].parmctrl_string)
772 : {
773 0 : elem = pk_algo_table[algoidx].parmelem_string;
774 0 : ctrl = pk_algo_table[algoidx].parmctrl_string;
775 0 : for (; *elem; ctrl++, elem++)
776 : {
777 : int is_int;
778 :
779 0 : if ( (*ctrl & 0x80) && !elem[1] )
780 : {
781 : /* Hack to allow reading a raw value. */
782 0 : is_int = 1;
783 0 : len = parmderlen;
784 : }
785 : else
786 : {
787 0 : if (!parmderlen)
788 : {
789 0 : xfree (parm_oid);
790 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
791 : }
792 0 : c = *parmder++; parmderlen--;
793 0 : if ( c != *ctrl )
794 : {
795 0 : xfree (parm_oid);
796 0 : return gpg_error (GPG_ERR_UNEXPECTED_TAG);
797 : }
798 0 : is_int = c == 0x02;
799 0 : TLV_LENGTH (parmder);
800 : }
801 0 : if (is_int && *elem != '-') /* Take this integer. */
802 : {
803 : char tmp[2];
804 :
805 0 : put_stringbuf (&sb, "(");
806 0 : tmp[0] = *elem; tmp[1] = 0;
807 0 : put_stringbuf_sexp (&sb, tmp);
808 0 : put_stringbuf_mem_sexp (&sb, parmder, len);
809 0 : parmder += len;
810 0 : parmderlen -= len;
811 0 : put_stringbuf (&sb, ")");
812 : }
813 : }
814 : }
815 :
816 :
817 : /* FIXME: We don't release the stringbuf in case of error
818 : better let the macro jump to a label */
819 6 : elem = pk_algo_table[algoidx].elem_string;
820 6 : ctrl = pk_algo_table[algoidx].ctrl_string;
821 24 : for (; *elem; ctrl++, elem++)
822 : {
823 : int is_int;
824 :
825 18 : if ( (*ctrl & 0x80) && !elem[1] )
826 : {
827 : /* Hack to allow reading a raw value. */
828 0 : is_int = 1;
829 0 : len = derlen;
830 : }
831 : else
832 : {
833 18 : if (!derlen)
834 : {
835 0 : xfree (parm_oid);
836 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
837 : }
838 18 : c = *der++; derlen--;
839 18 : if ( c != *ctrl )
840 : {
841 0 : xfree (parm_oid);
842 0 : return gpg_error (GPG_ERR_UNEXPECTED_TAG);
843 : }
844 18 : is_int = c == 0x02;
845 18 : TLV_LENGTH (der);
846 : }
847 18 : if (is_int && *elem != '-') /* Take this integer. */
848 : {
849 : char tmp[2];
850 :
851 12 : put_stringbuf (&sb, "(");
852 12 : tmp[0] = *elem; tmp[1] = 0;
853 12 : put_stringbuf_sexp (&sb, tmp);
854 12 : put_stringbuf_mem_sexp (&sb, der, len);
855 12 : der += len;
856 12 : derlen -= len;
857 12 : put_stringbuf (&sb, ")");
858 : }
859 : }
860 6 : put_stringbuf (&sb, "))");
861 6 : xfree (parm_oid);
862 :
863 6 : *r_string = get_stringbuf (&sb);
864 6 : if (!*r_string)
865 0 : return gpg_error (GPG_ERR_ENOMEM);
866 :
867 6 : return 0;
868 : }
869 :
870 :
871 : /* Match the algorithm string given in BUF which is of length BUFLEN
872 : with the known algorithms from our table and returns the table
873 : entries for the DER encoded OID. If WITH_SIG is true, the table of
874 : signature algorithms is consulted first. */
875 : static const unsigned char *
876 6 : oid_from_buffer (const unsigned char *buf, int buflen, int *oidlen,
877 : pkalgo_t *r_pkalgo, int with_sig)
878 : {
879 : int i;
880 :
881 : /* Ignore an optional "oid." prefix. */
882 6 : if (buflen > 4 && buf[3] == '.' && digitp (buf+4)
883 0 : && ((buf[0] == 'o' && buf[1] == 'i' && buf[2] == 'd')
884 0 : ||(buf[0] == 'O' && buf[1] == 'I' && buf[2] == 'D')))
885 : {
886 0 : buf += 4;
887 0 : buflen -= 4;
888 : }
889 :
890 6 : if (with_sig)
891 : {
892 : /* Scan the signature table first. */
893 0 : for (i=0; sig_algo_table[i].oid; i++)
894 : {
895 0 : if (!sig_algo_table[i].supported)
896 0 : continue;
897 0 : if (buflen == strlen (sig_algo_table[i].oidstring)
898 0 : && !memcmp (buf, sig_algo_table[i].oidstring, buflen))
899 0 : break;
900 0 : if (buflen == strlen (sig_algo_table[i].algo_string)
901 0 : && !memcmp (buf, sig_algo_table[i].algo_string, buflen))
902 0 : break;
903 : }
904 0 : if (sig_algo_table[i].oid)
905 : {
906 0 : *r_pkalgo = sig_algo_table[i].pkalgo;
907 0 : *oidlen = sig_algo_table[i].oidlen;
908 0 : return sig_algo_table[i].oid;
909 : }
910 : }
911 :
912 : /* Scan the standard table. */
913 6 : for (i=0; pk_algo_table[i].oid; i++)
914 : {
915 6 : if (!pk_algo_table[i].supported)
916 0 : continue;
917 6 : if (buflen == strlen (pk_algo_table[i].oidstring)
918 0 : && !memcmp (buf, pk_algo_table[i].oidstring, buflen))
919 0 : break;
920 6 : if (buflen == strlen (pk_algo_table[i].algo_string)
921 6 : && !memcmp (buf, pk_algo_table[i].algo_string, buflen))
922 6 : break;
923 : }
924 6 : if (!pk_algo_table[i].oid)
925 0 : return NULL;
926 :
927 6 : *r_pkalgo = pk_algo_table[i].pkalgo;
928 6 : *oidlen = pk_algo_table[i].oidlen;
929 6 : return pk_algo_table[i].oid;
930 : }
931 :
932 :
933 : /* Take a public-key S-Exp and convert it into a DER encoded
934 : publicKeyInfo */
935 : gpg_error_t
936 6 : _ksba_keyinfo_from_sexp (ksba_const_sexp_t sexp,
937 : unsigned char **r_der, size_t *r_derlen)
938 : {
939 : gpg_error_t err;
940 : const unsigned char *s;
941 : char *endp;
942 : unsigned long n, n1;
943 : const unsigned char *oid;
944 : int oidlen;
945 6 : unsigned char *curve_oid = NULL;
946 : size_t curve_oidlen;
947 : pkalgo_t pkalgo;
948 : int i;
949 : struct {
950 : const char *name;
951 : int namelen;
952 : const unsigned char *value;
953 : int valuelen;
954 : } parm[10];
955 : int parmidx;
956 : int idxtbl[10];
957 : int idxtbllen;
958 : const char *parmdesc, *algoparmdesc;
959 6 : ksba_writer_t writer = NULL;
960 6 : void *algoparmseq_value = NULL;
961 : size_t algoparmseq_len;
962 6 : void *bitstr_value = NULL;
963 : size_t bitstr_len;
964 :
965 6 : if (!sexp)
966 0 : return gpg_error (GPG_ERR_INV_VALUE);
967 :
968 6 : s = sexp;
969 6 : if (*s != '(')
970 0 : return gpg_error (GPG_ERR_INV_SEXP);
971 6 : s++;
972 :
973 6 : n = strtoul (s, &endp, 10);
974 6 : s = endp;
975 6 : if (!n || *s != ':')
976 0 : return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
977 6 : s++;
978 6 : if (n != 10 || memcmp (s, "public-key", 10))
979 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
980 6 : s += 10;
981 6 : if (*s != '(')
982 0 : return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
983 6 : s++;
984 :
985 : /* Break out the algorithm ID */
986 6 : n = strtoul (s, &endp, 10);
987 6 : s = endp;
988 6 : if (!n || *s != ':')
989 0 : return gpg_error (GPG_ERR_INV_SEXP); /* we don't allow empty lengths */
990 6 : s++;
991 6 : oid = oid_from_buffer (s, n, &oidlen, &pkalgo, 0);
992 6 : if (!oid)
993 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
994 6 : s += n;
995 :
996 : /* Collect all the values */
997 18 : for (parmidx = 0; *s != ')' ; parmidx++)
998 : {
999 12 : if (parmidx >= DIM(parm))
1000 0 : return gpg_error (GPG_ERR_GENERAL);
1001 12 : if (*s != '(')
1002 0 : return gpg_error (digitp(s)? GPG_ERR_UNKNOWN_SEXP:GPG_ERR_INV_SEXP);
1003 12 : s++;
1004 12 : n = strtoul (s, &endp, 10);
1005 12 : s = endp;
1006 12 : if (!n || *s != ':')
1007 0 : return gpg_error (GPG_ERR_INV_SEXP);
1008 12 : s++;
1009 12 : parm[parmidx].name = s;
1010 12 : parm[parmidx].namelen = n;
1011 12 : s += n;
1012 12 : if (!digitp(s))
1013 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
1014 :
1015 12 : n = strtoul (s, &endp, 10);
1016 12 : s = endp;
1017 12 : if (!n || *s != ':')
1018 0 : return gpg_error (GPG_ERR_INV_SEXP);
1019 12 : s++;
1020 12 : parm[parmidx].value = s;
1021 12 : parm[parmidx].valuelen = n;
1022 12 : s += n;
1023 12 : if ( *s != ')')
1024 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
1025 12 : s++;
1026 : }
1027 6 : s++;
1028 : /* We need another closing parenthesis. */
1029 6 : if ( *s != ')' )
1030 0 : return gpg_error (GPG_ERR_INV_SEXP);
1031 :
1032 : /* Describe the parameters in the order we want them and construct
1033 : IDXTBL to access them. For DSA wie also set algoparmdesc so
1034 : that we can later build the parameters for the
1035 : algorithmIdentifier. */
1036 6 : algoparmdesc = NULL;
1037 6 : switch (pkalgo)
1038 : {
1039 6 : case PKALGO_RSA: parmdesc = "ne"; break;
1040 0 : case PKALGO_DSA: parmdesc = "y" ; algoparmdesc = "pqg"; break;
1041 0 : case PKALGO_ECC: parmdesc = "Cq"; break;
1042 0 : default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
1043 : }
1044 :
1045 6 : idxtbllen = 0;
1046 18 : for (s = parmdesc; *s; s++)
1047 : {
1048 30 : for (i=0; i < parmidx; i++)
1049 : {
1050 18 : assert (idxtbllen < DIM (idxtbl));
1051 18 : switch (*s)
1052 : {
1053 : case 'C': /* Magic value for "curve". */
1054 0 : if (parm[i].namelen == 5 && !memcmp (parm[i].name, "curve", 5))
1055 : {
1056 0 : idxtbl[idxtbllen++] = i;
1057 0 : i = parmidx; /* Break inner loop. */
1058 : }
1059 0 : break;
1060 : default:
1061 18 : if (parm[i].namelen == 1 && parm[i].name[0] == *s)
1062 : {
1063 12 : idxtbl[idxtbllen++] = i;
1064 12 : i = parmidx; /* Break inner loop. */
1065 : }
1066 18 : break;
1067 : }
1068 : }
1069 : }
1070 6 : if (idxtbllen != strlen (parmdesc))
1071 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1072 :
1073 6 : if (pkalgo == PKALGO_ECC)
1074 : {
1075 0 : curve_oid = get_ecc_curve_oid (parm[idxtbl[0]].value,
1076 0 : parm[idxtbl[0]].valuelen,
1077 : &curve_oidlen);
1078 0 : if (!curve_oid)
1079 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1080 : }
1081 :
1082 :
1083 : /* Create write object. */
1084 6 : err = ksba_writer_new (&writer);
1085 6 : if (err)
1086 0 : goto leave;
1087 6 : err = ksba_writer_set_mem (writer, 1024);
1088 6 : if (err)
1089 0 : goto leave;
1090 :
1091 : /* We create the keyinfo in 2 steps:
1092 :
1093 : 1. We build the inner one and encapsulate it in a bit string.
1094 :
1095 : 2. We create the outer sequence include the algorithm identifier
1096 : and the bit string from step 1.
1097 : */
1098 6 : if (pkalgo == PKALGO_ECC)
1099 : {
1100 : /* Write the bit string header and the number of unused bits. */
1101 0 : err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
1102 0 : 0, parm[idxtbl[1]].valuelen + 1);
1103 0 : if (!err)
1104 0 : err = ksba_writer_write (writer, "", 1);
1105 : /* And the actual raw value. */
1106 0 : if (!err)
1107 0 : err = ksba_writer_write (writer, parm[idxtbl[1]].value,
1108 0 : parm[idxtbl[1]].valuelen);
1109 0 : if (err)
1110 0 : goto leave;
1111 :
1112 : }
1113 : else /* RSA and DSA */
1114 : {
1115 : /* Calculate the size of the sequence value and the size of the
1116 : bit string value. NOt ethat in case there is only one
1117 : integer to write, no sequence is used. */
1118 18 : for (n=0, i=0; i < idxtbllen; i++ )
1119 : {
1120 12 : n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
1121 12 : parm[idxtbl[i]].valuelen);
1122 12 : n += parm[idxtbl[i]].valuelen;
1123 : }
1124 :
1125 6 : n1 = 1; /* # of unused bits. */
1126 6 : if (idxtbllen > 1)
1127 6 : n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
1128 6 : n1 += n;
1129 :
1130 : /* Write the bit string header and the number of unused bits. */
1131 6 : err = _ksba_ber_write_tl (writer, TYPE_BIT_STRING, CLASS_UNIVERSAL,
1132 : 0, n1);
1133 6 : if (!err)
1134 6 : err = ksba_writer_write (writer, "", 1);
1135 6 : if (err)
1136 0 : goto leave;
1137 :
1138 : /* Write the sequence tag and the integers. */
1139 6 : if (idxtbllen > 1)
1140 6 : err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1,n);
1141 6 : if (err)
1142 0 : goto leave;
1143 18 : for (i=0; i < idxtbllen; i++)
1144 : {
1145 : /* fixme: we should make sure that the integer conforms to the
1146 : ASN.1 encoding rules. */
1147 12 : err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
1148 12 : parm[idxtbl[i]].valuelen);
1149 12 : if (!err)
1150 12 : err = ksba_writer_write (writer, parm[idxtbl[i]].value,
1151 12 : parm[idxtbl[i]].valuelen);
1152 12 : if (err)
1153 0 : goto leave;
1154 : }
1155 : }
1156 :
1157 : /* Get the encoded bit string. */
1158 6 : bitstr_value = ksba_writer_snatch_mem (writer, &bitstr_len);
1159 6 : if (!bitstr_value)
1160 : {
1161 0 : err = gpg_error (GPG_ERR_ENOMEM);
1162 0 : goto leave;
1163 : }
1164 :
1165 : /* If the algorithmIdentifier requires a sequence with parameters,
1166 : build them now. We can reuse the IDXTBL for that. */
1167 6 : if (algoparmdesc)
1168 : {
1169 0 : idxtbllen = 0;
1170 0 : for (s = algoparmdesc; *s; s++)
1171 : {
1172 0 : for (i=0; i < parmidx; i++)
1173 : {
1174 0 : assert (idxtbllen < DIM (idxtbl));
1175 0 : if (parm[i].namelen == 1 && parm[i].name[0] == *s)
1176 : {
1177 0 : idxtbl[idxtbllen++] = i;
1178 0 : break;
1179 : }
1180 : }
1181 : }
1182 0 : if (idxtbllen != strlen (algoparmdesc))
1183 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1184 :
1185 0 : err = ksba_writer_set_mem (writer, 1024);
1186 0 : if (err)
1187 0 : goto leave;
1188 :
1189 : /* Calculate the size of the sequence. */
1190 0 : for (n=0, i=0; i < idxtbllen; i++ )
1191 : {
1192 0 : n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
1193 0 : parm[idxtbl[i]].valuelen);
1194 0 : n += parm[idxtbl[i]].valuelen;
1195 : }
1196 : /* n += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n); */
1197 :
1198 : /* Write the sequence tag followed by the integers. */
1199 0 : err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
1200 0 : if (err)
1201 0 : goto leave;
1202 0 : for (i=0; i < idxtbllen; i++)
1203 : {
1204 0 : err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
1205 0 : parm[idxtbl[i]].valuelen);
1206 0 : if (!err)
1207 0 : err = ksba_writer_write (writer, parm[idxtbl[i]].value,
1208 0 : parm[idxtbl[i]].valuelen);
1209 0 : if (err)
1210 0 : goto leave;
1211 : }
1212 :
1213 : /* Get the encoded sequence. */
1214 0 : algoparmseq_value = ksba_writer_snatch_mem (writer, &algoparmseq_len);
1215 0 : if (!algoparmseq_value)
1216 : {
1217 0 : err = gpg_error (GPG_ERR_ENOMEM);
1218 0 : goto leave;
1219 : }
1220 : }
1221 : else
1222 6 : algoparmseq_len = 0;
1223 :
1224 : /* Reinitialize the buffer to create the outer sequence. */
1225 6 : err = ksba_writer_set_mem (writer, 1024);
1226 6 : if (err)
1227 0 : goto leave;
1228 :
1229 : /* Calulate lengths. */
1230 6 : n = _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
1231 6 : n += oidlen;
1232 6 : if (algoparmseq_len)
1233 : {
1234 0 : n += algoparmseq_len;
1235 : }
1236 6 : else if (pkalgo == PKALGO_ECC)
1237 : {
1238 0 : n += _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL,
1239 : 0, curve_oidlen);
1240 0 : n += curve_oidlen;
1241 : }
1242 6 : else if (pkalgo == PKALGO_RSA)
1243 : {
1244 6 : n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
1245 : }
1246 :
1247 6 : n1 = n;
1248 6 : n1 += _ksba_ber_count_tl (TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
1249 6 : n1 += bitstr_len;
1250 :
1251 : /* The outer sequence. */
1252 6 : err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n1);
1253 6 : if (err)
1254 0 : goto leave;
1255 :
1256 : /* The sequence. */
1257 6 : err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
1258 6 : if (err)
1259 0 : goto leave;
1260 :
1261 : /* The object id. */
1262 6 : err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID,CLASS_UNIVERSAL, 0, oidlen);
1263 6 : if (!err)
1264 6 : err = ksba_writer_write (writer, oid, oidlen);
1265 6 : if (err)
1266 0 : goto leave;
1267 :
1268 : /* The parameter. */
1269 6 : if (algoparmseq_len)
1270 : {
1271 0 : err = ksba_writer_write (writer, algoparmseq_value, algoparmseq_len);
1272 : }
1273 6 : else if (pkalgo == PKALGO_ECC)
1274 : {
1275 0 : err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL,
1276 : 0, curve_oidlen);
1277 0 : if (!err)
1278 0 : err = ksba_writer_write (writer, curve_oid, curve_oidlen);
1279 : }
1280 6 : else if (pkalgo == PKALGO_RSA)
1281 : {
1282 6 : err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
1283 : }
1284 6 : if (err)
1285 0 : goto leave;
1286 :
1287 : /* Append the pre-constructed bit string. */
1288 6 : err = ksba_writer_write (writer, bitstr_value, bitstr_len);
1289 6 : if (err)
1290 0 : goto leave;
1291 :
1292 : /* Get the result. */
1293 6 : *r_der = ksba_writer_snatch_mem (writer, r_derlen);
1294 6 : if (!*r_der)
1295 0 : err = gpg_error (GPG_ERR_ENOMEM);
1296 :
1297 : leave:
1298 6 : ksba_writer_release (writer);
1299 6 : xfree (bitstr_value);
1300 6 : xfree (curve_oid);
1301 6 : return err;
1302 : }
1303 :
1304 :
1305 : /* Take a sig-val s-expression and convert it into a DER encoded
1306 : algorithmInfo. Unfortunately this function clones a lot of code
1307 : from _ksba_keyinfo_from_sexp. */
1308 : gpg_error_t
1309 0 : _ksba_algoinfo_from_sexp (ksba_const_sexp_t sexp,
1310 : unsigned char **r_der, size_t *r_derlen)
1311 : {
1312 : gpg_error_t err;
1313 : const unsigned char *s;
1314 : char *endp;
1315 : unsigned long n;
1316 : const unsigned char *oid;
1317 : int oidlen;
1318 0 : unsigned char *curve_oid = NULL;
1319 : size_t curve_oidlen;
1320 : pkalgo_t pkalgo;
1321 : int i;
1322 : struct {
1323 : const char *name;
1324 : int namelen;
1325 : const unsigned char *value;
1326 : int valuelen;
1327 : } parm[10];
1328 : int parmidx;
1329 : int idxtbl[10];
1330 : int idxtbllen;
1331 : const char *parmdesc, *algoparmdesc;
1332 0 : ksba_writer_t writer = NULL;
1333 0 : void *algoparmseq_value = NULL;
1334 : size_t algoparmseq_len;
1335 :
1336 0 : if (!sexp)
1337 0 : return gpg_error (GPG_ERR_INV_VALUE);
1338 :
1339 0 : s = sexp;
1340 0 : if (*s != '(')
1341 0 : return gpg_error (GPG_ERR_INV_SEXP);
1342 0 : s++;
1343 :
1344 0 : n = strtoul (s, &endp, 10);
1345 0 : s = endp;
1346 0 : if (!n || *s != ':')
1347 0 : return gpg_error (GPG_ERR_INV_SEXP); /* We don't allow empty lengths. */
1348 0 : s++;
1349 0 : if (n == 7 && !memcmp (s, "sig-val", 7))
1350 0 : s += 7;
1351 0 : else if (n == 10 && !memcmp (s, "public-key", 10))
1352 0 : s += 10;
1353 : else
1354 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1355 :
1356 0 : if (*s != '(')
1357 0 : return gpg_error (digitp (s)? GPG_ERR_UNKNOWN_SEXP : GPG_ERR_INV_SEXP);
1358 0 : s++;
1359 :
1360 : /* Break out the algorithm ID */
1361 0 : n = strtoul (s, &endp, 10);
1362 0 : s = endp;
1363 0 : if (!n || *s != ':')
1364 0 : return gpg_error (GPG_ERR_INV_SEXP); /* We don't allow empty lengths. */
1365 0 : s++;
1366 0 : oid = oid_from_buffer (s, n, &oidlen, &pkalgo, 1);
1367 0 : if (!oid)
1368 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
1369 0 : s += n;
1370 :
1371 : /* Collect all the values */
1372 0 : for (parmidx = 0; *s != ')' ; parmidx++)
1373 : {
1374 0 : if (parmidx >= DIM(parm))
1375 0 : return gpg_error (GPG_ERR_GENERAL);
1376 0 : if (*s != '(')
1377 0 : return gpg_error (digitp(s)? GPG_ERR_UNKNOWN_SEXP:GPG_ERR_INV_SEXP);
1378 0 : s++;
1379 0 : n = strtoul (s, &endp, 10);
1380 0 : s = endp;
1381 0 : if (!n || *s != ':')
1382 0 : return gpg_error (GPG_ERR_INV_SEXP);
1383 0 : s++;
1384 0 : parm[parmidx].name = s;
1385 0 : parm[parmidx].namelen = n;
1386 0 : s += n;
1387 0 : if (!digitp(s))
1388 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
1389 :
1390 0 : n = strtoul (s, &endp, 10);
1391 0 : s = endp;
1392 0 : if (!n || *s != ':')
1393 0 : return gpg_error (GPG_ERR_INV_SEXP);
1394 0 : s++;
1395 0 : parm[parmidx].value = s;
1396 0 : parm[parmidx].valuelen = n;
1397 0 : s += n;
1398 0 : if ( *s != ')')
1399 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP); /* ... or invalid S-Exp. */
1400 0 : s++;
1401 : }
1402 0 : s++;
1403 : /* We need another closing parenthesis. */
1404 0 : if ( *s != ')' )
1405 0 : return gpg_error (GPG_ERR_INV_SEXP);
1406 :
1407 : /* Describe the parameters in the order we want them and construct
1408 : IDXTBL to access them. For DSA wie also set algoparmdesc so
1409 : that we can later build the parameters for the
1410 : algorithmIdentifier. */
1411 0 : algoparmdesc = NULL;
1412 0 : switch (pkalgo)
1413 : {
1414 0 : case PKALGO_RSA: parmdesc = ""; break;
1415 0 : case PKALGO_DSA: parmdesc = "" ; algoparmdesc = "pqg"; break;
1416 0 : case PKALGO_ECC: parmdesc = "C"; break;
1417 0 : default: return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
1418 : }
1419 :
1420 0 : idxtbllen = 0;
1421 0 : for (s = parmdesc; *s; s++)
1422 : {
1423 0 : for (i=0; i < parmidx; i++)
1424 : {
1425 0 : assert (idxtbllen < DIM (idxtbl));
1426 0 : switch (*s)
1427 : {
1428 : case 'C': /* Magic value for "curve". */
1429 0 : if (parm[i].namelen == 5 && !memcmp (parm[i].name, "curve", 5))
1430 : {
1431 0 : idxtbl[idxtbllen++] = i;
1432 0 : i = parmidx; /* Break inner loop. */
1433 : }
1434 0 : break;
1435 : default:
1436 0 : if (parm[i].namelen == 1 && parm[i].name[0] == *s)
1437 : {
1438 0 : idxtbl[idxtbllen++] = i;
1439 0 : i = parmidx; /* Break inner loop. */
1440 : }
1441 0 : break;
1442 : }
1443 : }
1444 : }
1445 0 : if (idxtbllen != strlen (parmdesc))
1446 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1447 :
1448 0 : if (pkalgo == PKALGO_ECC)
1449 : {
1450 0 : curve_oid = get_ecc_curve_oid (parm[idxtbl[0]].value,
1451 0 : parm[idxtbl[0]].valuelen,
1452 : &curve_oidlen);
1453 0 : if (!curve_oid)
1454 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1455 : }
1456 :
1457 :
1458 : /* Create write object. */
1459 0 : err = ksba_writer_new (&writer);
1460 0 : if (err)
1461 0 : goto leave;
1462 0 : err = ksba_writer_set_mem (writer, 1024);
1463 0 : if (err)
1464 0 : goto leave;
1465 :
1466 : /* Create the sequence of the algorithm identifier. */
1467 :
1468 : /* If the algorithmIdentifier requires a sequence with parameters,
1469 : build them now. We can reuse the IDXTBL for that. */
1470 0 : if (algoparmdesc)
1471 : {
1472 0 : idxtbllen = 0;
1473 0 : for (s = algoparmdesc; *s; s++)
1474 : {
1475 0 : for (i=0; i < parmidx; i++)
1476 : {
1477 0 : assert (idxtbllen < DIM (idxtbl));
1478 0 : if (parm[i].namelen == 1 && parm[i].name[0] == *s)
1479 : {
1480 0 : idxtbl[idxtbllen++] = i;
1481 0 : break;
1482 : }
1483 : }
1484 : }
1485 0 : if (idxtbllen != strlen (algoparmdesc))
1486 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
1487 :
1488 0 : err = ksba_writer_set_mem (writer, 1024);
1489 0 : if (err)
1490 0 : goto leave;
1491 :
1492 : /* Calculate the size of the sequence. */
1493 0 : for (n=0, i=0; i < idxtbllen; i++ )
1494 : {
1495 0 : n += _ksba_ber_count_tl (TYPE_INTEGER, CLASS_UNIVERSAL, 0,
1496 0 : parm[idxtbl[i]].valuelen);
1497 0 : n += parm[idxtbl[i]].valuelen;
1498 : }
1499 :
1500 : /* Write the sequence tag followed by the integers. */
1501 0 : err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
1502 0 : if (err)
1503 0 : goto leave;
1504 0 : for (i=0; i < idxtbllen; i++)
1505 : {
1506 0 : err = _ksba_ber_write_tl (writer, TYPE_INTEGER, CLASS_UNIVERSAL, 0,
1507 0 : parm[idxtbl[i]].valuelen);
1508 0 : if (!err)
1509 0 : err = ksba_writer_write (writer, parm[idxtbl[i]].value,
1510 0 : parm[idxtbl[i]].valuelen);
1511 0 : if (err)
1512 0 : goto leave;
1513 : }
1514 :
1515 : /* Get the encoded sequence. */
1516 0 : algoparmseq_value = ksba_writer_snatch_mem (writer, &algoparmseq_len);
1517 0 : if (!algoparmseq_value)
1518 : {
1519 0 : err = gpg_error (GPG_ERR_ENOMEM);
1520 0 : goto leave;
1521 : }
1522 : }
1523 : else
1524 0 : algoparmseq_len = 0;
1525 :
1526 : /* Reinitialize the buffer to create the sequence. */
1527 0 : err = ksba_writer_set_mem (writer, 1024);
1528 0 : if (err)
1529 0 : goto leave;
1530 :
1531 : /* Calulate lengths. */
1532 0 : n = _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
1533 0 : n += oidlen;
1534 0 : if (algoparmseq_len)
1535 : {
1536 0 : n += algoparmseq_len;
1537 : }
1538 0 : else if (pkalgo == PKALGO_ECC)
1539 : {
1540 0 : n += _ksba_ber_count_tl (TYPE_OBJECT_ID, CLASS_UNIVERSAL,
1541 : 0, curve_oidlen);
1542 0 : n += curve_oidlen;
1543 : }
1544 0 : else if (pkalgo == PKALGO_RSA)
1545 : {
1546 0 : n += _ksba_ber_count_tl (TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
1547 : }
1548 :
1549 : /* Write the sequence. */
1550 0 : err = _ksba_ber_write_tl (writer, TYPE_SEQUENCE, CLASS_UNIVERSAL, 1, n);
1551 0 : if (err)
1552 0 : goto leave;
1553 :
1554 : /* Write the object id. */
1555 0 : err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL, 0, oidlen);
1556 0 : if (!err)
1557 0 : err = ksba_writer_write (writer, oid, oidlen);
1558 0 : if (err)
1559 0 : goto leave;
1560 :
1561 : /* Write the parameters. */
1562 0 : if (algoparmseq_len)
1563 : {
1564 0 : err = ksba_writer_write (writer, algoparmseq_value, algoparmseq_len);
1565 : }
1566 0 : else if (pkalgo == PKALGO_ECC)
1567 : {
1568 : /* We only support the namedCuve choice for ECC parameters. */
1569 0 : err = _ksba_ber_write_tl (writer, TYPE_OBJECT_ID, CLASS_UNIVERSAL,
1570 : 0, curve_oidlen);
1571 0 : if (!err)
1572 0 : err = ksba_writer_write (writer, curve_oid, curve_oidlen);
1573 : }
1574 0 : else if (pkalgo == PKALGO_RSA)
1575 : {
1576 0 : err = _ksba_ber_write_tl (writer, TYPE_NULL, CLASS_UNIVERSAL, 0, 0);
1577 : }
1578 0 : if (err)
1579 0 : goto leave;
1580 :
1581 : /* Get the result. */
1582 0 : *r_der = ksba_writer_snatch_mem (writer, r_derlen);
1583 0 : if (!*r_der)
1584 0 : err = gpg_error (GPG_ERR_ENOMEM);
1585 :
1586 : leave:
1587 0 : ksba_writer_release (writer);
1588 0 : xfree (curve_oid);
1589 0 : return err;
1590 : }
1591 :
1592 :
1593 :
1594 : /* Mode 0: work as described under _ksba_sigval_to_sexp
1595 : mode 1: work as described under _ksba_encval_to_sexp */
1596 : static gpg_error_t
1597 1 : cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen,
1598 : ksba_sexp_t *r_string)
1599 : {
1600 : gpg_error_t err;
1601 : const struct algo_table_s *algo_table;
1602 : int c;
1603 : size_t nread, off, len;
1604 : int algoidx;
1605 : int is_bitstr;
1606 : const unsigned char *ctrl;
1607 : const char *elem;
1608 : struct stringbuf sb;
1609 :
1610 : /* FIXME: The entire function is very similar to keyinfo_to_sexp */
1611 1 : *r_string = NULL;
1612 :
1613 1 : if (!mode)
1614 1 : algo_table = sig_algo_table;
1615 : else
1616 0 : algo_table = enc_algo_table;
1617 :
1618 :
1619 1 : err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr,
1620 : NULL, NULL, NULL);
1621 1 : if (err)
1622 0 : return err;
1623 :
1624 : /* look into our table of supported algorithms */
1625 1 : for (algoidx=0; algo_table[algoidx].oid; algoidx++)
1626 : {
1627 1 : if ( len == algo_table[algoidx].oidlen
1628 1 : && !memcmp (der+off, algo_table[algoidx].oid, len))
1629 1 : break;
1630 : }
1631 1 : if (!algo_table[algoidx].oid)
1632 0 : return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM);
1633 1 : if (!algo_table[algoidx].supported)
1634 0 : return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
1635 :
1636 1 : der += nread;
1637 1 : derlen -= nread;
1638 :
1639 1 : if (is_bitstr)
1640 : { /* Funny: X.509 defines the signature value as a bit string but
1641 : CMS as an octet string - for ease of implementation we always
1642 : allow both */
1643 1 : if (!derlen)
1644 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
1645 1 : c = *der++; derlen--;
1646 1 : if (c)
1647 0 : fprintf (stderr, "warning: number of unused bits is not zero\n");
1648 : }
1649 :
1650 : /* fixme: we should calculate the initial length form the size of the
1651 : sequence, so that we don't neen a realloc later */
1652 1 : init_stringbuf (&sb, 100);
1653 1 : put_stringbuf (&sb, mode? "(7:enc-val(":"(7:sig-val(");
1654 1 : put_stringbuf_sexp (&sb, algo_table[algoidx].algo_string);
1655 :
1656 : /* FIXME: We don't release the stringbuf in case of error
1657 : better let the macro jump to a label */
1658 1 : elem = algo_table[algoidx].elem_string;
1659 1 : ctrl = algo_table[algoidx].ctrl_string;
1660 2 : for (; *elem; ctrl++, elem++)
1661 : {
1662 : int is_int;
1663 :
1664 1 : if ( (*ctrl & 0x80) && !elem[1] )
1665 : { /* Hack to allow a raw value */
1666 1 : is_int = 1;
1667 1 : len = derlen;
1668 : }
1669 : else
1670 : {
1671 0 : if (!derlen)
1672 0 : return gpg_error (GPG_ERR_INV_KEYINFO);
1673 0 : c = *der++; derlen--;
1674 0 : if ( c != *ctrl )
1675 0 : return gpg_error (GPG_ERR_UNEXPECTED_TAG);
1676 0 : is_int = c == 0x02;
1677 0 : TLV_LENGTH (der);
1678 : }
1679 1 : if (is_int && *elem != '-')
1680 : { /* take this integer */
1681 : char tmp[2];
1682 :
1683 1 : put_stringbuf (&sb, "(");
1684 1 : tmp[0] = *elem; tmp[1] = 0;
1685 1 : put_stringbuf_sexp (&sb, tmp);
1686 1 : put_stringbuf_mem_sexp (&sb, der, len);
1687 1 : der += len;
1688 1 : derlen -= len;
1689 1 : put_stringbuf (&sb, ")");
1690 : }
1691 : }
1692 1 : put_stringbuf (&sb, ")");
1693 1 : if (!mode && algo_table[algoidx].digest_string)
1694 : {
1695 : /* Insert the hash algorithm if included in the OID. */
1696 1 : put_stringbuf (&sb, "(4:hash");
1697 1 : put_stringbuf_sexp (&sb, algo_table[algoidx].digest_string);
1698 1 : put_stringbuf (&sb, ")");
1699 : }
1700 1 : put_stringbuf (&sb, ")");
1701 :
1702 1 : *r_string = get_stringbuf (&sb);
1703 1 : if (!*r_string)
1704 0 : return gpg_error (GPG_ERR_ENOMEM);
1705 :
1706 1 : return 0;
1707 : }
1708 :
1709 : /* Assume that DER is a buffer of length DERLEN with a DER encoded
1710 : Asn.1 structure like this:
1711 :
1712 : SEQUENCE {
1713 : algorithm OBJECT IDENTIFIER,
1714 : parameters ANY DEFINED BY algorithm OPTIONAL }
1715 : signature BIT STRING
1716 :
1717 : We only allow parameters == NULL.
1718 :
1719 : The function parses this structure and creates a S-Exp suitable to be
1720 : used as signature value in Libgcrypt:
1721 :
1722 : (sig-val
1723 : (<algo>
1724 : (<param_name1> <mpi>)
1725 : ...
1726 : (<param_namen> <mpi>))
1727 : (hash algo))
1728 :
1729 : The S-Exp will be returned in a string which the caller must free.
1730 : We don't pass an ASN.1 node here but a plain memory block. */
1731 : gpg_error_t
1732 1 : _ksba_sigval_to_sexp (const unsigned char *der, size_t derlen,
1733 : ksba_sexp_t *r_string)
1734 : {
1735 1 : return cryptval_to_sexp (0, der, derlen, r_string);
1736 : }
1737 :
1738 :
1739 : /* Assume that der is a buffer of length DERLEN with a DER encoded
1740 : Asn.1 structure like this:
1741 :
1742 : SEQUENCE {
1743 : algorithm OBJECT IDENTIFIER,
1744 : parameters ANY DEFINED BY algorithm OPTIONAL }
1745 : encryptedKey OCTET STRING
1746 :
1747 : We only allow parameters == NULL.
1748 :
1749 : The function parses this structure and creates a S-Exp suitable to be
1750 : used as encrypted value in Libgcrypt's public key functions:
1751 :
1752 : (enc-val
1753 : (<algo>
1754 : (<param_name1> <mpi>)
1755 : ...
1756 : (<param_namen> <mpi>)
1757 : ))
1758 :
1759 : The S-Exp will be returned in a string which the caller must free.
1760 : We don't pass an ASN.1 node here but a plain memory block. */
1761 : gpg_error_t
1762 0 : _ksba_encval_to_sexp (const unsigned char *der, size_t derlen,
1763 : ksba_sexp_t *r_string)
1764 : {
1765 0 : return cryptval_to_sexp (1, der, derlen, r_string);
1766 : }
|