1 /* protect.c - Un/Protect a secret key
2 * Copyright (C) 1998, 1999, 2000, 2001, 2002,
3 * 2003, 2007, 2009 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
33 #include "sexp-parse.h"
35 #define PROT_CIPHER GCRY_CIPHER_AES
36 #define PROT_CIPHER_STRING "aes"
37 #define PROT_CIPHER_KEYLEN (128/8)
40 /* A table containing the information needed to create a protected
45 int prot_from
, prot_to
;
47 { "rsa", "nedpqu", 2, 5 },
48 { "dsa", "pqgyx", 4, 4 },
49 { "elg", "pgyx", 3, 3 },
55 hash_passphrase (const char *passphrase
, int hashalgo
,
57 const unsigned char *s2ksalt
, unsigned long s2kcount
,
58 unsigned char *key
, size_t keylen
);
62 /* Calculate the MIC for a private key S-Exp. SHA1HASH should point to
63 a 20 byte buffer. This function is suitable for any algorithms. */
65 calculate_mic (const unsigned char *plainkey
, unsigned char *sha1hash
)
67 const unsigned char *hash_begin
, *hash_end
;
68 const unsigned char *s
;
73 return gpg_error (GPG_ERR_INV_SEXP
);
77 return gpg_error (GPG_ERR_INV_SEXP
);
78 if (!smatch (&s
, n
, "private-key"))
79 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
81 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
86 return gpg_error (GPG_ERR_INV_SEXP
);
87 s
+= n
; /* skip over the algorithm name */
94 return gpg_error (GPG_ERR_INV_SEXP
);
98 return gpg_error (GPG_ERR_INV_SEXP
);
101 return gpg_error (GPG_ERR_INV_SEXP
);
105 return gpg_error (GPG_ERR_INV_SEXP
);
109 gcry_md_hash_buffer (GCRY_MD_SHA1
, sha1hash
,
110 hash_begin
, hash_end
- hash_begin
);
117 /* Encrypt the parameter block starting at PROTBEGIN with length
118 PROTLEN using the utf8 encoded key PASSPHRASE and return the entire
119 encrypted block in RESULT or return with an error code. SHA1HASH
120 is the 20 byte SHA-1 hash required for the integrity code.
122 The parameter block is expected to be an incomplete S-Expression of
123 the form (example in advanced format):
125 (d #046129F..[some bytes not shown]..81#)
126 (p #00e861b..[some bytes not shown]..f1#)
127 (q #00f7a7c..[some bytes not shown]..61#)
128 (u #304559a..[some bytes not shown]..9b#)
130 the returned block is the S-Expression:
132 (protected mode (parms) encrypted_octet_string)
136 do_encryption (const unsigned char *protbegin
, size_t protlen
,
137 const char *passphrase
, const unsigned char *sha1hash
,
138 unsigned char **result
, size_t *resultlen
)
141 const char *modestr
= "openpgp-s2k3-sha1-" PROT_CIPHER_STRING
"-cbc";
142 int blklen
, enclen
, outlen
;
143 unsigned char *iv
= NULL
;
147 int saltpos
, ivpos
, encpos
;
152 rc
= gcry_cipher_open (&hd
, PROT_CIPHER
, GCRY_CIPHER_MODE_CBC
,
158 /* We need to work on a copy of the data because this makes it
159 easier to add the trailer and the padding and more important we
160 have to prefix the text with 2 parenthesis, so we have to
161 allocate enough space for:
163 ((<parameter_list>)(4:hash4:sha120:<hashvalue>)) + padding
165 We always append a full block of random bytes as padding but
166 encrypt only what is needed for a full blocksize. */
167 blklen
= gcry_cipher_get_algo_blklen (PROT_CIPHER
);
168 outlen
= 2 + protlen
+ 2 + 6 + 6 + 23 + 2 + blklen
;
169 enclen
= outlen
/blklen
* blklen
;
170 outbuf
= gcry_malloc_secure (outlen
);
175 /* Allocate random bytes to be used as IV, padding and s2k salt. */
176 iv
= xtrymalloc (blklen
*2+8);
178 rc
= gpg_error (GPG_ERR_ENOMEM
);
179 gcry_create_nonce (iv
, blklen
*2+8);
180 rc
= gcry_cipher_setiv (hd
, iv
, blklen
);
185 size_t keylen
= PROT_CIPHER_KEYLEN
;
187 key
= gcry_malloc_secure (keylen
);
192 rc
= hash_passphrase (passphrase
, GCRY_MD_SHA1
,
193 3, iv
+2*blklen
, 96, key
, keylen
);
195 rc
= gcry_cipher_setkey (hd
, key
, keylen
);
204 memcpy (p
, protbegin
, protlen
);
206 memcpy (p
, ")(4:hash4:sha120:", 17);
208 memcpy (p
, sha1hash
, 20);
212 memcpy (p
, iv
+blklen
, blklen
);
214 assert ( p
- outbuf
== outlen
);
215 rc
= gcry_cipher_encrypt (hd
, outbuf
, enclen
, NULL
, 0);
217 gcry_cipher_close (hd
);
225 /* Now allocate the buffer we want to return. This is
227 (protected openpgp-s2k3-sha1-aes-cbc
228 ((sha1 salt no_of_iterations) 16byte_iv)
229 encrypted_octet_string)
231 in canoncical format of course. We use asprintf and %n modifier
232 and dummy values as placeholders. */
234 ("(9:protected%d:%s((4:sha18:%n_8bytes_2:96)%d:%n%*s)%d:%n%*s)",
235 (int)strlen (modestr
), modestr
,
237 blklen
, &ivpos
, blklen
, "",
238 enclen
, &encpos
, enclen
, "");
241 gpg_error_t tmperr
= out_of_core ();
246 *resultlen
= strlen (p
);
247 *result
= (unsigned char*)p
;
248 memcpy (p
+saltpos
, iv
+2*blklen
, 8);
249 memcpy (p
+ivpos
, iv
, blklen
);
250 memcpy (p
+encpos
, outbuf
, enclen
);
258 /* Protect the key encoded in canonical format in PLAINKEY. We assume
259 a valid S-Exp here. */
261 agent_protect (const unsigned char *plainkey
, const char *passphrase
,
262 unsigned char **result
, size_t *resultlen
)
265 const unsigned char *s
;
266 const unsigned char *hash_begin
, *hash_end
;
267 const unsigned char *prot_begin
, *prot_end
, *real_end
;
270 unsigned char hashvalue
[20];
271 char timestamp_exp
[35];
272 unsigned char *protected;
278 /* Create an S-expression with the procted-at timestamp. */
279 memcpy (timestamp_exp
, "(12:protected-at15:", 19);
280 gnupg_get_isotime (timestamp_exp
+19);
281 timestamp_exp
[19+15] = ')';
283 /* Parse original key. */
286 return gpg_error (GPG_ERR_INV_SEXP
);
291 return gpg_error (GPG_ERR_INV_SEXP
);
292 if (!smatch (&s
, n
, "private-key"))
293 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
295 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
301 return gpg_error (GPG_ERR_INV_SEXP
);
303 for (infidx
=0; protect_info
[infidx
].algo
304 && !smatch (&s
, n
, protect_info
[infidx
].algo
); infidx
++)
306 if (!protect_info
[infidx
].algo
)
307 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM
);
309 prot_begin
= prot_end
= NULL
;
310 for (i
=0; (c
=protect_info
[infidx
].parmlist
[i
]); i
++)
312 if (i
== protect_info
[infidx
].prot_from
)
315 return gpg_error (GPG_ERR_INV_SEXP
);
320 return gpg_error (GPG_ERR_INV_SEXP
);
321 if (n
!= 1 || c
!= *s
)
322 return gpg_error (GPG_ERR_INV_SEXP
);
326 return gpg_error (GPG_ERR_INV_SEXP
);
327 s
+=n
; /* skip value */
329 return gpg_error (GPG_ERR_INV_SEXP
);
331 if (i
== protect_info
[infidx
].prot_to
)
335 if (*s
!= ')' || !prot_begin
|| !prot_end
)
336 return gpg_error (GPG_ERR_INV_SEXP
);
340 /* skip to the end of the S-exp */
342 rc
= sskip (&s
, &depth
);
349 /* Hash the stuff. Because the timestamp_exp won't get protected,
350 we can't simply hash a continuous buffer but need to use several
352 rc
= gcry_md_open (&md
, GCRY_MD_SHA1
, 0 );
355 gcry_md_write (md
, hash_begin
, hash_end
- hash_begin
);
356 gcry_md_write (md
, timestamp_exp
, 35);
357 gcry_md_write (md
, ")", 1);
358 memcpy (hashvalue
, gcry_md_read (md
, GCRY_MD_SHA1
), 20);
361 rc
= do_encryption (prot_begin
, prot_end
- prot_begin
+ 1,
362 passphrase
, hashvalue
,
363 &protected, &protectedlen
);
367 /* Now create the protected version of the key. Note that the 10
368 extra bytes are for for the inserted "protected-" string (the
369 beginning of the plaintext reads: "((11:private-key(" ). The 35
370 term is the space for (12:protected-at15:<timestamp>). */
372 + (prot_begin
-plainkey
)
375 + (real_end
-prot_end
));
376 *result
= p
= xtrymalloc (*resultlen
);
379 gpg_error_t tmperr
= out_of_core ();
383 memcpy (p
, "(21:protected-", 14);
385 memcpy (p
, plainkey
+4, prot_begin
- plainkey
- 4);
386 p
+= prot_begin
- plainkey
- 4;
387 memcpy (p
, protected, protectedlen
);
390 memcpy (p
, timestamp_exp
, 35);
393 memcpy (p
, prot_end
+1, real_end
- prot_end
);
394 p
+= real_end
- prot_end
;
395 assert ( p
- *result
== *resultlen
);
402 /* Do the actual decryption and check the return list for consistency. */
404 do_decryption (const unsigned char *protected, size_t protectedlen
,
405 const char *passphrase
,
406 const unsigned char *s2ksalt
, unsigned long s2kcount
,
407 const unsigned char *iv
, size_t ivlen
,
408 unsigned char **result
)
413 unsigned char *outbuf
;
416 blklen
= gcry_cipher_get_algo_blklen (PROT_CIPHER
);
417 if (protectedlen
< 4 || (protectedlen
%blklen
))
418 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION
);
420 rc
= gcry_cipher_open (&hd
, PROT_CIPHER
, GCRY_CIPHER_MODE_CBC
,
425 outbuf
= gcry_malloc_secure (protectedlen
);
429 rc
= gcry_cipher_setiv (hd
, iv
, ivlen
);
433 size_t keylen
= PROT_CIPHER_KEYLEN
;
435 key
= gcry_malloc_secure (keylen
);
440 rc
= hash_passphrase (passphrase
, GCRY_MD_SHA1
,
441 3, s2ksalt
, s2kcount
, key
, keylen
);
443 rc
= gcry_cipher_setkey (hd
, key
, keylen
);
448 rc
= gcry_cipher_decrypt (hd
, outbuf
, protectedlen
,
449 protected, protectedlen
);
450 gcry_cipher_close (hd
);
456 /* Do a quick check first. */
457 if (*outbuf
!= '(' && outbuf
[1] != '(')
460 return gpg_error (GPG_ERR_BAD_PASSPHRASE
);
462 /* Check that we have a consistent S-Exp. */
463 reallen
= gcry_sexp_canon_len (outbuf
, protectedlen
, NULL
, NULL
);
464 if (!reallen
|| (reallen
+ blklen
< protectedlen
) )
467 return gpg_error (GPG_ERR_BAD_PASSPHRASE
);
474 /* Merge the parameter list contained in CLEARTEXT with the original
475 protect lists PROTECTEDKEY by replacing the list at REPLACEPOS.
476 Return the new list in RESULT and the MIC value in the 20 byte
477 buffer SHA1HASH. CUTOFF and CUTLEN will receive the offset and the
478 length of the resulting list which should go into the MIC
479 calculation but then be removed. */
481 merge_lists (const unsigned char *protectedkey
,
483 const unsigned char *cleartext
,
484 unsigned char *sha1hash
,
485 unsigned char **result
, size_t *resultlen
,
486 size_t *cutoff
, size_t *cutlen
)
488 size_t n
, newlistlen
;
489 unsigned char *newlist
, *p
;
490 const unsigned char *s
;
491 const unsigned char *startpos
, *endpos
;
500 return gpg_error (GPG_ERR_BUG
);
502 /* Estimate the required size of the resulting list. We have a large
503 safety margin of >20 bytes (MIC hash from CLEARTEXT and the
504 removed "protected-" */
505 newlistlen
= gcry_sexp_canon_len (protectedkey
, 0, NULL
, NULL
);
507 return gpg_error (GPG_ERR_BUG
);
508 n
= gcry_sexp_canon_len (cleartext
, 0, NULL
, NULL
);
510 return gpg_error (GPG_ERR_BUG
);
512 newlist
= gcry_malloc_secure (newlistlen
);
514 return out_of_core ();
516 /* Copy the initial segment */
517 strcpy ((char*)newlist
, "(11:private-key");
519 memcpy (p
, protectedkey
+15+10, replacepos
-15-10);
520 p
+= replacepos
-15-10;
522 /* copy the cleartext */
524 if (*s
!= '(' && s
[1] != '(')
525 return gpg_error (GPG_ERR_BUG
); /*we already checked this */
547 /* Intermezzo: Get the MIC */
552 if (!smatch (&s
, n
, "hash"))
555 if (!smatch (&s
, n
, "sha1"))
560 memcpy (sha1hash
, s
, 20);
566 /* append the parameter list */
567 memcpy (p
, startpos
, endpos
- startpos
);
568 p
+= endpos
- startpos
;
570 /* Skip over the protected list element in the original list. */
571 s
= protectedkey
+ replacepos
;
578 /* Record the position of the optional protected-at expression. */
581 const unsigned char *save_s
= s
;
584 if (smatch (&s
, n
, "protected-at"))
590 *cutlen
= s
- save_s
;
595 i
= 2; /* we are inside this level */
599 assert (s
[-1] == ')');
600 endpos
= s
; /* one behind the end of the list */
602 /* Append the rest. */
604 *cutoff
= p
- newlist
;
605 memcpy (p
, startpos
, endpos
- startpos
);
606 p
+= endpos
- startpos
;
611 *resultlen
= newlistlen
;
615 wipememory (newlist
, newlistlen
);
620 wipememory (newlist
, newlistlen
);
622 return gpg_error (GPG_ERR_INV_SEXP
);
627 /* Unprotect the key encoded in canonical format. We assume a valid
628 S-Exp here. If a protected-at item is available, its value will
629 be stored at protocted_at unless this is NULL. */
631 agent_unprotect (const unsigned char *protectedkey
, const char *passphrase
,
632 gnupg_isotime_t protected_at
,
633 unsigned char **result
, size_t *resultlen
)
636 const unsigned char *s
;
637 const unsigned char *protect_list
;
640 unsigned char sha1hash
[20], sha1hash2
[20];
641 const unsigned char *s2ksalt
;
642 unsigned long s2kcount
;
643 const unsigned char *iv
;
644 const unsigned char *prot_begin
;
645 unsigned char *cleartext
;
646 unsigned char *final
;
648 size_t cutoff
, cutlen
;
655 return gpg_error (GPG_ERR_INV_SEXP
);
659 return gpg_error (GPG_ERR_INV_SEXP
);
660 if (!smatch (&s
, n
, "protected-private-key"))
661 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
663 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
667 return gpg_error (GPG_ERR_INV_SEXP
);
669 for (infidx
=0; protect_info
[infidx
].algo
670 && !smatch (&s
, n
, protect_info
[infidx
].algo
); infidx
++)
672 if (!protect_info
[infidx
].algo
)
673 return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM
);
676 /* See wether we have a protected-at timestamp. */
677 protect_list
= s
; /* Save for later. */
686 return gpg_error (GPG_ERR_INV_SEXP
);
687 if (smatch (&s
, n
, "protected-at"))
691 return gpg_error (GPG_ERR_INV_SEXP
);
693 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
694 memcpy (protected_at
, s
, 15);
695 protected_at
[15] = 0;
706 /* Now find the list with the protected information. Here is an
707 example for such a list:
708 (protected openpgp-s2k3-sha1-aes-cbc
709 ((sha1 <salt> <count>) <Initialization_Vector>)
716 return gpg_error (GPG_ERR_INV_SEXP
);
721 return gpg_error (GPG_ERR_INV_SEXP
);
722 if (smatch (&s
, n
, "protected"))
733 return gpg_error (GPG_ERR_INV_SEXP
);
734 if (!smatch (&s
, n
, "openpgp-s2k3-sha1-" PROT_CIPHER_STRING
"-cbc"))
735 return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION
);
736 if (*s
!= '(' || s
[1] != '(')
737 return gpg_error (GPG_ERR_INV_SEXP
);
741 return gpg_error (GPG_ERR_INV_SEXP
);
742 if (!smatch (&s
, n
, "sha1"))
743 return gpg_error (GPG_ERR_UNSUPPORTED_PROTECTION
);
746 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION
);
751 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION
);
752 /* We expect a list close as next, so we can simply use strtoul()
753 here. We might want to check that we only have digits - but this
754 is nothing we should worry about */
756 return gpg_error (GPG_ERR_INV_SEXP
);
757 s2kcount
= strtoul ((const char*)s
, NULL
, 10);
759 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION
);
761 s
++; /* skip list end */
764 if (n
!= 16) /* Wrong blocksize for IV (we support only aes-128). */
765 return gpg_error (GPG_ERR_CORRUPTED_PROTECTION
);
769 return gpg_error (GPG_ERR_INV_SEXP
);
773 return gpg_error (GPG_ERR_INV_SEXP
);
775 rc
= do_decryption (s
, n
,
776 passphrase
, s2ksalt
, s2kcount
,
782 rc
= merge_lists (protectedkey
, prot_begin
-protectedkey
, cleartext
,
783 sha1hash
, &final
, &finallen
, &cutoff
, &cutlen
);
784 /* Albeit cleartext has been allocated in secure memory and thus
785 xfree will wipe it out, we do an extra wipe just in case
786 somethings goes badly wrong. */
787 wipememory (cleartext
, n
);
792 rc
= calculate_mic (final
, sha1hash2
);
793 if (!rc
&& memcmp (sha1hash
, sha1hash2
, 20))
794 rc
= gpg_error (GPG_ERR_CORRUPTED_PROTECTION
);
797 wipememory (final
, finallen
);
801 /* Now remove tha part which is included in the MIC but should not
802 go into the final thing. */
805 memmove (final
+cutoff
, final
+cutoff
+cutlen
, finallen
-cutoff
-cutlen
);
810 *resultlen
= gcry_sexp_canon_len (final
, 0, NULL
, NULL
);
814 /* Check the type of the private key, this is one of the constants:
815 PRIVATE_KEY_UNKNOWN if we can't figure out the type (this is the
816 value 0), PRIVATE_KEY_CLEAR for an unprotected private key.
817 PRIVATE_KEY_PROTECTED for an protected private key or
818 PRIVATE_KEY_SHADOWED for a sub key where the secret parts are stored
821 agent_private_key_type (const unsigned char *privatekey
)
823 const unsigned char *s
;
828 return PRIVATE_KEY_UNKNOWN
;
832 return PRIVATE_KEY_UNKNOWN
;
833 if (smatch (&s
, n
, "protected-private-key"))
834 return PRIVATE_KEY_PROTECTED
;
835 if (smatch (&s
, n
, "shadowed-private-key"))
836 return PRIVATE_KEY_SHADOWED
;
837 if (smatch (&s
, n
, "private-key"))
838 return PRIVATE_KEY_CLEAR
;
839 return PRIVATE_KEY_UNKNOWN
;
844 /* Transform a passphrase into a suitable key of length KEYLEN and
845 store this key in the caller provided buffer KEY. The caller must
846 provide an HASHALGO, a valid S2KMODE (see rfc-2440) and depending on
847 that mode an S2KSALT of 8 random bytes and an S2KCOUNT (a suitable
850 Returns an error code on failure. */
852 hash_passphrase (const char *passphrase
, int hashalgo
,
854 const unsigned char *s2ksalt
,
855 unsigned long s2kcount
,
856 unsigned char *key
, size_t keylen
)
862 int pwlen
= strlen (passphrase
);
864 if ( (s2kmode
!= 0 && s2kmode
!= 1 && s2kmode
!= 3)
865 || !hashalgo
|| !keylen
|| !key
|| !passphrase
)
866 return gpg_error (GPG_ERR_INV_VALUE
);
867 if ((s2kmode
== 1 ||s2kmode
== 3) && !s2ksalt
)
868 return gpg_error (GPG_ERR_INV_VALUE
);
870 rc
= gcry_md_open (&md
, hashalgo
, GCRY_MD_FLAG_SECURE
);
874 for (pass
=0; used
< keylen
; pass
++)
879 for (i
=0; i
< pass
; i
++) /* preset the hash context */
880 gcry_md_putc (md
, 0);
883 if (s2kmode
== 1 || s2kmode
== 3)
885 int len2
= pwlen
+ 8;
886 unsigned long count
= len2
;
890 count
= (16ul + (s2kcount
& 15)) << ((s2kcount
>> 4) + 6);
897 gcry_md_write (md
, s2ksalt
, 8);
898 gcry_md_write (md
, passphrase
, pwlen
);
902 gcry_md_write (md
, s2ksalt
, count
);
905 gcry_md_write (md
, s2ksalt
, 8);
907 gcry_md_write (md
, passphrase
, count
);
911 gcry_md_write (md
, passphrase
, pwlen
);
914 i
= gcry_md_get_algo_dlen (hashalgo
);
915 if (i
> keylen
- used
)
917 memcpy (key
+used
, gcry_md_read (md
, hashalgo
), i
);
927 /* Create an canonical encoded S-expression with the shadow info from
928 a card's SERIALNO and the IDSTRING. */
930 make_shadow_info (const char *serialno
, const char *idstring
)
937 for (s
=serialno
, n
=0; *s
&& s
[1]; s
+= 2)
940 info
= p
= xtrymalloc (1 + sizeof numbuf
+ n
941 + sizeof numbuf
+ strlen (idstring
) + 1 + 1);
945 p
= stpcpy (p
, smklen (numbuf
, sizeof numbuf
, n
, NULL
));
946 for (s
=serialno
; *s
&& s
[1]; s
+= 2)
947 *(unsigned char *)p
++ = xtoi_2 (s
);
948 p
= stpcpy (p
, smklen (numbuf
, sizeof numbuf
, strlen (idstring
), NULL
));
949 p
= stpcpy (p
, idstring
);
952 return (unsigned char *)info
;
957 /* Create a shadow key from a public key. We use the shadow protocol
958 "ti-v1" and insert the S-expressionn SHADOW_INFO. The resulting
959 S-expression is returned in an allocated buffer RESULT will point
960 to. The input parameters are expected to be valid canonicalized
963 agent_shadow_key (const unsigned char *pubkey
,
964 const unsigned char *shadow_info
,
965 unsigned char **result
)
967 const unsigned char *s
;
968 const unsigned char *point
;
972 size_t pubkey_len
= gcry_sexp_canon_len (pubkey
, 0, NULL
,NULL
);
973 size_t shadow_info_len
= gcry_sexp_canon_len (shadow_info
, 0, NULL
,NULL
);
975 if (!pubkey_len
|| !shadow_info_len
)
976 return gpg_error (GPG_ERR_INV_VALUE
);
979 return gpg_error (GPG_ERR_INV_SEXP
);
984 return gpg_error (GPG_ERR_INV_SEXP
);
985 if (!smatch (&s
, n
, "public-key"))
986 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
988 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
993 return gpg_error (GPG_ERR_INV_SEXP
);
994 s
+= n
; /* skip over the algorithm name */
999 return gpg_error (GPG_ERR_INV_SEXP
);
1004 return gpg_error (GPG_ERR_INV_SEXP
);
1008 return gpg_error (GPG_ERR_INV_SEXP
);
1009 s
+=n
; /* skip value */
1011 return gpg_error (GPG_ERR_INV_SEXP
);
1015 point
= s
; /* insert right before the point */
1018 assert (depth
== 1);
1020 /* Calculate required length by taking in account: the "shadowed-"
1021 prefix, the "shadowed", "t1-v1" as well as some parenthesis */
1022 n
= 12 + pubkey_len
+ 1 + 3+8 + 2+5 + shadow_info_len
+ 1;
1023 *result
= xtrymalloc (n
);
1026 return out_of_core ();
1027 p
= stpcpy (p
, "(20:shadowed-private-key");
1028 /* (10:public-key ...)*/
1029 memcpy (p
, pubkey
+14, point
- (pubkey
+14));
1030 p
+= point
- (pubkey
+14);
1031 p
= stpcpy (p
, "(8:shadowed5:t1-v1");
1032 memcpy (p
, shadow_info
, shadow_info_len
);
1033 p
+= shadow_info_len
;
1035 memcpy (p
, point
, pubkey_len
- (point
- pubkey
));
1036 p
+= pubkey_len
- (point
- pubkey
);
1041 /* Parse a canonical encoded shadowed key and return a pointer to the
1042 inner list with the shadow_info */
1044 agent_get_shadow_info (const unsigned char *shadowkey
,
1045 unsigned char const **shadow_info
)
1047 const unsigned char *s
;
1053 return gpg_error (GPG_ERR_INV_SEXP
);
1058 return gpg_error (GPG_ERR_INV_SEXP
);
1059 if (!smatch (&s
, n
, "shadowed-private-key"))
1060 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
1062 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
1067 return gpg_error (GPG_ERR_INV_SEXP
);
1068 s
+= n
; /* skip over the algorithm name */
1073 return gpg_error (GPG_ERR_UNKNOWN_SEXP
);
1075 return gpg_error (GPG_ERR_INV_SEXP
);
1080 return gpg_error (GPG_ERR_INV_SEXP
);
1081 if (smatch (&s
, n
, "shadowed"))
1086 return gpg_error (GPG_ERR_INV_SEXP
);
1087 s
+=n
; /* skip value */
1089 return gpg_error (GPG_ERR_INV_SEXP
);
1093 /* Found the shadowed list, S points to the protocol */
1096 return gpg_error (GPG_ERR_INV_SEXP
);
1097 if (smatch (&s
, n
, "t1-v1"))
1100 return gpg_error (GPG_ERR_INV_SEXP
);
1104 return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL
);
1109 /* Parse the canonical encoded SHADOW_INFO S-expression. On success
1110 the hex encoded serial number is returned as a malloced strings at
1111 R_HEXSN and the Id string as a malloced string at R_IDSTR. On
1112 error an error code is returned and NULL is stored at the result
1113 parameters addresses. If the serial number or the ID string is not
1114 required, NULL may be passed for them. */
1116 parse_shadow_info (const unsigned char *shadow_info
,
1117 char **r_hexsn
, char **r_idstr
)
1119 const unsigned char *s
;
1129 return gpg_error (GPG_ERR_INV_SEXP
);
1133 return gpg_error (GPG_ERR_INV_SEXP
);
1137 *r_hexsn
= bin2hex (s
, n
, NULL
);
1139 return gpg_error_from_syserror ();
1151 return gpg_error (GPG_ERR_INV_SEXP
);
1156 *r_idstr
= xtrymalloc (n
+1);
1164 return gpg_error_from_syserror ();
1166 memcpy (*r_idstr
, s
, n
);