*** empty log message ***
[gnutls.git] / libextra / opencdk / pubkey.c
blob18154229df52a7434d500c87dc401759ddeac989
1 /* -*- Mode: C; c-file-style: "bsd" -*-
2 * pubkey.c - Public key API
3 * Copyright (C) 2007 Free Software Foundation, Inc.
4 * Copyright (C) 2002, 2003 Timo Schulz
6 * This file is part of OpenCDK.
8 * OpenCDK is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * OpenCDK is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with OpenCDK; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26 #include <stdio.h>
28 #include "opencdk.h"
29 #include "main.h"
30 #include "packet.h"
31 #include "cipher.h"
34 static gcry_mpi_t *
35 convert_to_gcrympi( cdk_mpi_t m[4], int ncount )
37 gcry_mpi_t * d;
38 size_t nbytes = 0;
39 int i = 0, rc = 0;
41 if( !m || ncount > 4 )
42 return NULL;
43 d = cdk_calloc( ncount, sizeof *d );
44 if( !d )
45 return NULL;
46 for( i = 0; i < ncount; i++ ) {
47 nbytes = m[i]->bytes + 2;
48 if( gcry_mpi_scan( &d[i], GCRYMPI_FMT_PGP, m[i]->data, nbytes, &nbytes ) ) {
49 rc = CDK_Gcry_Error;
50 break;
53 if( rc ) {
54 _cdk_free_mpibuf( i, d );
55 d = NULL;
57 return d;
61 static int
62 seckey_to_sexp( gcry_sexp_t * r_skey, cdk_pkt_seckey_t sk )
64 gcry_sexp_t sexp = NULL;
65 gcry_mpi_t * mpk = NULL, * msk = NULL;
66 cdk_pkt_pubkey_t pk;
67 const char * fmt = NULL;
68 int ncount = 0, nscount = 0;
69 int rc = 0;
71 if( !r_skey || !sk || !sk->pk )
72 return CDK_Inv_Value;
74 pk = sk->pk;
75 ncount = cdk_pk_get_npkey( pk->pubkey_algo );
76 mpk = convert_to_gcrympi( pk->mpi, ncount );
77 if( !mpk )
78 return CDK_MPI_Error;
79 nscount = cdk_pk_get_nskey( sk->pubkey_algo );
80 msk = convert_to_gcrympi( sk->mpi, nscount );
81 if( !msk )
82 rc = CDK_MPI_Error;
83 if( !rc && is_RSA( sk->pubkey_algo ) ) {
84 fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))";
85 if( gcry_sexp_build( &sexp, NULL, fmt, mpk[0], mpk[1],
86 msk[0], msk[1], msk[2], msk[3] ) )
87 rc = CDK_Gcry_Error;
89 else if( !rc && is_ELG( sk->pubkey_algo ) ) {
90 fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))";
91 if( gcry_sexp_build( &sexp, NULL, fmt, mpk[0], mpk[1],
92 mpk[2], msk[0] ) )
93 rc = CDK_Gcry_Error;
95 else if( !rc && is_DSA( sk->pubkey_algo ) ) {
96 fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))";
97 if( gcry_sexp_build( &sexp, NULL, fmt, mpk[0], mpk[1], mpk[2],
98 mpk[3], msk[0] ) )
99 rc = CDK_Gcry_Error;
101 else
102 rc = CDK_Inv_Algo;
104 _cdk_free_mpibuf( ncount, mpk );
105 _cdk_free_mpibuf( nscount, msk );
106 *r_skey = sexp;
107 return rc;
111 static int
112 pubkey_to_sexp( gcry_sexp_t * r_key, cdk_pkt_pubkey_t pk )
114 gcry_sexp_t sexp = NULL;
115 gcry_mpi_t * m;
116 const char * fmt = NULL;
117 int ncount = 0;
118 int rc = 0;
120 if( !r_key || !pk )
121 return CDK_Inv_Value;
123 ncount = cdk_pk_get_npkey( pk->pubkey_algo );
124 m = convert_to_gcrympi( pk->mpi, ncount );
125 if( !m )
126 return CDK_MPI_Error;
127 if( is_RSA( pk->pubkey_algo ) ) {
128 fmt = "(public-key(openpgp-rsa(n%m)(e%m)))";
129 if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
130 rc = CDK_Gcry_Error;
132 else if( is_ELG( pk->pubkey_algo ) ) {
133 fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))";
134 if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1], m[2] ) )
135 rc = CDK_Gcry_Error;
137 else if( is_DSA( pk->pubkey_algo ) ) {
138 fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))";
139 if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1], m[2], m[3] ) )
140 rc = CDK_Gcry_Error;
142 else
143 rc = CDK_Inv_Algo;
144 _cdk_free_mpibuf( ncount, m );
145 *r_key = sexp;
146 return rc;
150 static int
151 enckey_to_sexp( gcry_sexp_t * r_sexp, gcry_mpi_t esk )
153 gcry_sexp_t sexp = NULL;
154 int rc = 0;
156 if( !r_sexp || !esk )
157 return CDK_Inv_Value;
158 if( gcry_sexp_build( &sexp, NULL, "%m", esk ) )
159 rc = CDK_Gcry_Error;
160 *r_sexp = sexp;
161 return rc;
165 static int
166 digest_to_sexp( gcry_sexp_t * r_md, int algo, const byte * md, size_t mdlen )
168 gcry_sexp_t sexp = NULL;
169 gcry_mpi_t m = NULL;
170 size_t nbytes = 0;
171 int rc = 0;
173 if( !r_md || !md )
174 return CDK_Inv_Value;
175 nbytes = mdlen ? mdlen : cdk_md_get_algo_dlen( algo );
176 if( !nbytes )
177 return CDK_Inv_Algo;
178 if( gcry_mpi_scan( &m, GCRYMPI_FMT_USG, md, nbytes, &nbytes ) )
179 return CDK_Gcry_Error;
180 if( gcry_sexp_build( &sexp, NULL, "%m", m ) )
181 rc = CDK_Gcry_Error;
182 if( !rc )
183 *r_md = sexp;
184 gcry_mpi_release( m );
185 return rc;
189 static int
190 sexp_to_bitmpi( gcry_sexp_t sexp, const char * val, cdk_mpi_t * ret_buf )
192 gcry_sexp_t list = NULL;
193 gcry_mpi_t m = NULL;
194 cdk_mpi_t buf = NULL;
195 size_t nbits = 0, nbytes = 0;
196 int rc = 0;
198 if( !sexp || !val || !ret_buf )
199 return CDK_Inv_Value;
201 list = gcry_sexp_find_token( sexp, val, 0 );
202 if( !list )
203 return CDK_Gcry_Error;
204 m = gcry_sexp_nth_mpi( list, 1, 0 );
205 if( !m ) {
206 gcry_sexp_release( list );
207 return CDK_Gcry_Error;
209 nbits = gcry_mpi_get_nbits( m );
210 nbytes = (nbits + 7) / 8;
211 buf = cdk_calloc( 1, sizeof *buf + nbytes );
212 if( !buf ) {
213 rc = CDK_Out_Of_Core;
214 goto leave;
216 buf->data[0] = nbits >> 8;
217 buf->data[1] = nbits;
218 if( gcry_mpi_print( GCRYMPI_FMT_USG, NULL, nbytes, &nbytes, m ) )
219 rc = CDK_Gcry_Error;
220 else
221 if( gcry_mpi_print( GCRYMPI_FMT_USG, buf->data + 2, nbytes, &nbytes, m ) )
222 rc = CDK_Gcry_Error;
223 if( !rc ) {
224 buf->bytes = nbytes;
225 buf->bits = nbits;
226 *ret_buf = buf;
229 leave:
230 gcry_mpi_release( m );
231 gcry_sexp_release( list );
232 return rc;
236 static int
237 sexp_to_sig( cdk_pkt_signature_t sig, gcry_sexp_t sexp)
239 int rc = 0;
241 if( !sig || !sexp )
242 return CDK_Inv_Value;
244 if( is_RSA( sig->pubkey_algo ) )
245 return sexp_to_bitmpi( sexp, "s", &sig->mpi[0] );
246 else if( is_DSA( sig->pubkey_algo) || is_ELG( sig->pubkey_algo ) ) {
247 rc = sexp_to_bitmpi( sexp, "r", &sig->mpi[0] );
248 if( !rc )
249 rc = sexp_to_bitmpi( sexp, "s", &sig->mpi[1] );
250 return rc;
252 return CDK_Inv_Algo;
256 static int
257 sig_to_sexp( gcry_sexp_t * r_sig, cdk_pkt_signature_t sig )
259 gcry_sexp_t sexp = NULL;
260 gcry_mpi_t * m;
261 const char * fmt;
262 int ncount = 0;
263 int rc = 0;
265 if( !r_sig || !sig )
266 return CDK_Inv_Value;
268 ncount = cdk_pk_get_nsig( sig->pubkey_algo );
269 m = convert_to_gcrympi( sig->mpi, ncount );
270 if( !m )
271 return CDK_MPI_Error;
272 if( is_RSA( sig->pubkey_algo ) ) {
273 fmt = "(sig-val(openpgp-rsa(s%m)))";
274 if( gcry_sexp_build( &sexp, NULL, fmt, m[0] ) )
275 rc = CDK_Gcry_Error;
277 else if( is_ELG( sig->pubkey_algo ) ) {
278 fmt = "(sig-val(openpgp-elg(r%m)(s%m)))";
279 if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
280 rc = CDK_Gcry_Error;
282 else if( is_DSA( sig->pubkey_algo ) ) {
283 fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))";
284 if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
285 rc = CDK_Gcry_Error;
287 else
288 rc = CDK_Inv_Algo;
289 _cdk_free_mpibuf( ncount, m );
290 *r_sig = sexp;
291 return rc;
295 static int
296 sexp_to_pubenc( cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp)
298 int rc;
300 if( !sexp || !enc )
301 return CDK_Inv_Value;
303 if( is_RSA( enc->pubkey_algo) )
304 return sexp_to_bitmpi( sexp, "a", &enc->mpi[0] );
305 else if( is_ELG( enc->pubkey_algo) ) {
306 rc = sexp_to_bitmpi( sexp, "a", &enc->mpi[0] );
307 if( !rc )
308 rc = sexp_to_bitmpi( sexp, "b", &enc->mpi[1] );
309 return rc;
311 return CDK_Inv_Algo;
315 static int
316 pubenc_to_sexp( gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc)
318 gcry_sexp_t sexp = NULL;
319 gcry_mpi_t * m;
320 const char * fmt;
321 int ncount;
322 int rc = 0;
324 if( !r_sexp || !enc )
325 return CDK_Inv_Value;
327 ncount = cdk_pk_get_nenc( enc->pubkey_algo );
328 m = convert_to_gcrympi( enc->mpi, ncount );
329 if( !m )
330 return CDK_MPI_Error;
331 if( is_RSA( enc->pubkey_algo ) ) {
332 fmt = "(enc-val(openpgp-rsa((a%m))))";
333 if( gcry_sexp_build( &sexp, NULL, fmt, m[0] ) )
334 rc = CDK_Gcry_Error;
336 else if( is_ELG( enc->pubkey_algo ) ) {
337 fmt = "(enc-val(openpgp-elg((a%m)(b%m))))";
338 if( gcry_sexp_build( &sexp, NULL, fmt, m[0], m[1] ) )
339 rc = CDK_Gcry_Error;
341 else
342 rc = CDK_Inv_Algo;
343 _cdk_free_mpibuf( ncount, m );
344 *r_sexp = sexp;
345 return rc;
349 static int
350 is_unprotected( cdk_pkt_seckey_t sk )
352 if( sk->is_protected && !sk->mpi[0] )
353 return 0;
354 return 1;
359 * cdk_pk_encrypt:
360 * @pk: the public key
361 * @pke: the public key encrypted packet
362 * @esk: the actual session key
364 * Encrypt the session key in @esk and write its encrypted content
365 * into the @pke struct.
367 cdk_error_t
368 cdk_pk_encrypt( cdk_pkt_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
369 cdk_sesskey_t esk )
371 gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL;
372 int rc;
374 if( !pk || !esk || !pke )
375 return CDK_Inv_Value;
377 if( !KEY_CAN_ENCRYPT( pk->pubkey_algo ) )
378 return CDK_Inv_Algo;
380 rc = enckey_to_sexp( &s_data, esk->a );
381 if( !rc )
382 rc = pubkey_to_sexp( &s_pkey, pk );
383 if( !rc )
384 rc = gcry_pk_encrypt( &s_ciph, s_data, s_pkey );
385 if( !rc )
386 rc = sexp_to_pubenc( pke, s_ciph );
388 gcry_sexp_release( s_data );
389 gcry_sexp_release( s_pkey );
390 gcry_sexp_release( s_ciph );
391 return rc;
396 * cdk_pk_decrypt:
397 * @sk: the secret key
398 * @pke: public key encrypted packet
399 * @r_sk: the object to store the plain session key
401 * Decrypt the encrypted session key from @pke into @r_sk.
403 cdk_error_t
404 cdk_pk_decrypt( cdk_pkt_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
405 cdk_sesskey_t * r_sk )
407 gcry_sexp_t s_data = NULL, s_skey = NULL, s_plain = NULL;
408 int rc;
410 if( !sk || !r_sk || !pke )
411 return CDK_Inv_Value;
413 if( !is_unprotected( sk ) )
414 return CDK_Inv_Mode;
416 rc = seckey_to_sexp( &s_skey, sk );
417 if( !rc )
418 rc = pubenc_to_sexp( &s_data, pke );
419 if( !rc && gcry_pk_decrypt( &s_plain, s_data, s_skey ) )
420 rc = CDK_Gcry_Error;
421 if( !rc ) {
422 rc = cdk_sesskey_new( r_sk );
423 if( !rc )
424 (*r_sk)->a = gcry_sexp_nth_mpi( s_plain, 0, 0 );
427 gcry_sexp_release( s_data );
428 gcry_sexp_release( s_skey );
429 gcry_sexp_release( s_plain );
430 return rc;
435 * cdk_pk_sign:
436 * @sk: secret key
437 * @sig: signature
438 * @md: the message digest
440 * Sign the message digest from @md and write the result into @sig.
442 cdk_error_t
443 cdk_pk_sign( cdk_pkt_seckey_t sk, cdk_pkt_signature_t sig, const byte * md )
445 gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL;
446 byte * encmd = NULL;
447 size_t enclen = 0;
448 int nbits, rc;
450 if( !sk || !sk->pk || !sig || !md )
451 return CDK_Inv_Value;
453 if( !is_unprotected( sk ) )
454 return CDK_Inv_Mode;
456 if( !KEY_CAN_SIGN( sig->pubkey_algo ) )
457 return CDK_Inv_Algo;
459 nbits = cdk_pk_get_nbits( sk->pk );
460 rc = _cdk_digest_encode_pkcs1( &encmd, &enclen, sk->pk->pubkey_algo, md,
461 sig->digest_algo, nbits );
462 if( !rc )
463 rc = seckey_to_sexp( &s_skey, sk );
464 if( !rc )
465 rc = digest_to_sexp( &s_hash, sig->digest_algo, encmd, enclen );
466 if( !rc && gcry_pk_sign( &s_sig, s_hash, s_skey ) )
467 rc = CDK_Gcry_Error;
468 if( !rc )
469 rc = sexp_to_sig( sig, s_sig );
470 sig->digest_start[0] = md[0];
471 sig->digest_start[1] = md[1];
473 gcry_sexp_release( s_skey );
474 gcry_sexp_release( s_hash );
475 gcry_sexp_release( s_sig );
476 cdk_free( encmd );
477 return rc;
482 * cdk_pk_verify:
483 * @pk: the public key
484 * @sig: signature
485 * @md: the message digest
487 * Verify the signature in @sig and compare it with the message digest in @md.
489 cdk_error_t
490 cdk_pk_verify( cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
492 gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL;
493 byte * encmd = NULL;
494 size_t enclen = 0;
495 int nbits, rc;
497 if( !pk || !sig || !md )
498 return CDK_Inv_Value;
500 nbits = cdk_pk_get_nbits( pk );
501 rc = pubkey_to_sexp( &s_pkey, pk );
502 if( !rc )
503 rc = sig_to_sexp( &s_sig, sig );
504 if( !rc )
505 rc = _cdk_digest_encode_pkcs1( &encmd, &enclen, pk->pubkey_algo, md,
506 sig->digest_algo, nbits );
507 if( !rc )
508 rc = digest_to_sexp( &s_hash, sig->digest_algo, encmd, enclen );
509 if( !rc && gcry_pk_verify( s_sig, s_hash, s_pkey ) )
510 rc = CDK_Bad_Sig;
512 gcry_sexp_release( s_sig );
513 gcry_sexp_release( s_hash );
514 gcry_sexp_release( s_pkey );
515 cdk_free( encmd );
516 return rc;
521 cdk_pk_get_nbits( cdk_pkt_pubkey_t pk )
523 if( !pk || !pk->mpi[0] )
524 return 0;
525 return pk->mpi[0]->bits;
530 cdk_pk_get_npkey( int algo )
532 size_t bytes;
534 if (algo == 16)
535 algo = 20; /* XXX: libgcrypt returns 0 for 16 */
536 if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &bytes))
537 return 0;
539 return bytes;
544 cdk_pk_get_nskey( int algo )
546 size_t bytes;
548 if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &bytes))
549 return 0;
551 bytes -= cdk_pk_get_npkey( algo );
552 return bytes;
557 cdk_pk_get_nsig( int algo )
559 size_t bytes;
561 if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &bytes))
562 return 0;
563 return bytes;
568 cdk_pk_get_nenc( int algo )
570 size_t bytes;
572 if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &bytes))
573 return 0;
574 return bytes;
579 _cdk_pk_algo_usage( int algo )
581 int usage = 0;
583 switch( algo ) {
584 case CDK_PK_RSA : usage = PK_USAGE_SIGN | PK_USAGE_ENCR; break;
585 case CDK_PK_RSA_E: usage = PK_USAGE_ENCR; break;
586 case CDK_PK_RSA_S: usage = PK_USAGE_SIGN; break;
587 case CDK_PK_ELG : usage = PK_USAGE_SIGN | PK_USAGE_ENCR; break;
588 case CDK_PK_ELG_E: usage = PK_USAGE_ENCR; break;
589 case CDK_PK_DSA : usage = PK_USAGE_SIGN; break;
591 return usage;
596 _cdk_pk_test_algo( int algo, unsigned int usage_flags )
598 size_t n = usage_flags;
600 if( algo < 0 || algo > 110 )
601 return GPG_ERR_INV_PARAMETER;
602 return gcry_pk_algo_info( algo, GCRYCTL_TEST_ALGO, NULL, &n );
606 static int
607 read_mpi( cdk_mpi_t a, byte * buf, size_t * r_count, size_t * r_nbits )
609 if( !a || !buf || !r_count )
610 return CDK_Inv_Value;
612 if( a->bytes + 2 > *r_count )
613 return CDK_General_Error;
614 *r_count = a->bytes + 2;
615 memcpy( buf, a->data, *r_count );
616 if( r_nbits )
617 *r_nbits = a->bits;
618 return 0;
622 cdk_error_t
623 cdk_pk_get_mpi( cdk_pkt_pubkey_t pk, int idx,
624 byte * buf, size_t * r_count, size_t * r_nbits )
626 if( !pk || idx < 0 || !r_count )
627 return CDK_Inv_Value;
628 if( idx > cdk_pk_get_npkey( pk->pubkey_algo ) )
629 return CDK_Inv_Value;
630 return read_mpi( pk->mpi[idx], buf, r_count, r_nbits );
634 cdk_error_t
635 cdk_sk_get_mpi( cdk_pkt_seckey_t sk, int idx,
636 byte * buf, size_t * r_count, size_t * r_nbits)
638 if( !sk || idx < 0 || !r_count)
639 return CDK_Inv_Value;
640 if( idx > cdk_pk_get_nskey( sk->pubkey_algo ) )
641 return CDK_Inv_Value;
642 return read_mpi( sk->mpi[idx], buf, r_count, r_nbits );
646 static u16
647 checksum_mpi( cdk_mpi_t m )
649 int i;
650 u16 chksum = 0;
652 if( !m )
653 return 0;
654 for( i = 0; i < m->bytes + 2; i++)
655 chksum += m->data[i];
656 return chksum;
660 cdk_error_t
661 cdk_sk_unprotect( cdk_pkt_seckey_t sk, const char * pw )
663 cdk_cipher_hd_t hd;
664 cdk_dek_t dek = NULL;
665 cdk_mpi_t a;
666 u16 chksum = 0;
667 size_t ndata, nbits;
668 int j, i, dlen, pos = 0, nskey;
669 int rc;
670 byte * data = NULL;
672 if( !sk )
673 return CDK_Inv_Value;
675 nskey = cdk_pk_get_nskey( sk->pubkey_algo );
676 if( sk->is_protected ) {
677 rc = cdk_dek_from_passphrase( &dek, sk->protect.algo,
678 sk->protect.s2k, 0, pw );
679 if( rc )
680 return rc;
681 hd = cdk_cipher_open( sk->protect.algo, 1,
682 dek->key, dek->keylen,
683 sk->protect.iv, sk->protect.ivlen );
684 if( !hd ) {
685 cdk_free( dek );
686 return CDK_Inv_Algo;
688 wipemem( dek, sizeof dek );
689 cdk_dek_free( dek );
690 chksum = 0;
691 if( sk->version == 4 ) {
692 ndata = sk->enclen;
693 data = cdk_salloc( ndata, 1 );
694 if( !data )
695 return CDK_Out_Of_Core;
696 cdk_cipher_decrypt( hd, data, sk->encdata, ndata );
697 if( sk->protect.sha1chk ) {
698 /* This is the new SHA1 checksum method to detect tampering
699 with the key as used by the Klima/Rosa attack */
700 sk->csum = 0;
701 chksum = 1;
702 dlen = cdk_md_get_algo_dlen( CDK_MD_SHA1 );
703 if( ndata < dlen ) {
704 cdk_free( data );
705 return CDK_Inv_Packet;
707 else {
708 cdk_md_hd_t md = cdk_md_open( CDK_MD_SHA1, 1 );
709 if( !md )
710 return CDK_Gcry_Error;
711 cdk_md_write( md, data, ndata - dlen );
712 cdk_md_final( md );
713 if( !memcmp( cdk_md_read( md, CDK_MD_SHA1 ),
714 data + ndata - dlen, dlen ) )
715 chksum = 0; /* digest does match */
716 cdk_md_close( md );
719 else {
720 for( i = 0; i < ndata - 2; i++)
721 chksum += data[i];
722 sk->csum = data[ndata - 2] << 8 | data[ndata - 1];
724 if( sk->csum == chksum ) {
725 for( i = 0; i < nskey; i++ ) {
726 nbits = data[pos] << 8 | data[pos + 1];
727 ndata = (nbits + 7) / 8;
728 a = sk->mpi[i] = cdk_salloc( sizeof *a + ndata + 2, 1 );
729 if( !a ) {
730 cdk_free( data );
731 return CDK_Out_Of_Core;
733 a->bits = nbits;
734 a->bytes = ndata;
735 for( j = 0; j < ndata + 2; j++ )
736 a->data[j] = data[pos++];
739 wipemem( data, sk->enclen );
740 cdk_free( data );
742 else {
743 chksum = 0;
744 for( i = 0; i < nskey; i++ ) {
745 a = sk->mpi[i];
746 cdk_cipher_sync( hd );
747 cdk_cipher_decrypt( hd, a->data+2, a->data+2, a->bytes );
748 chksum += checksum_mpi( a );
751 cdk_cipher_close( hd );
753 else {
754 chksum = 0;
755 for( i = 0; i < nskey; i++ )
756 chksum += checksum_mpi( sk->mpi[i] );
758 if( chksum != sk->csum )
759 return CDK_Chksum_Error;
760 sk->is_protected = 0;
761 return 0;
765 cdk_error_t
766 cdk_sk_protect( cdk_pkt_seckey_t sk, const char * pass )
768 cdk_cipher_hd_t hd;
769 cdk_md_hd_t md;
770 cdk_mpi_t a;
771 cdk_dek_t dek;
772 cdk_s2k_t s2k;
773 byte * p;
774 size_t enclen = 0, nskey, i;
775 int rc;
777 rc = cdk_s2k_new( &s2k, 3, CDK_MD_SHA1, NULL );
778 if( rc )
779 return rc;
780 rc = cdk_dek_from_passphrase( &dek, CDK_CIPHER_3DES, s2k, 2, pass );
781 if( rc )
782 return rc;
784 nskey = cdk_pk_get_nskey( sk->pubkey_algo );
785 for( i = 0; i < nskey; i++ ) {
786 enclen += 2;
787 enclen += sk->mpi[i]->bytes;
789 p = sk->encdata = cdk_calloc( 1, enclen + 20 + 1 );
790 if( !p )
791 return CDK_Out_Of_Core;
792 enclen = 0;
793 for( i = 0; i < nskey; i++ ) {
794 a = sk->mpi[i];
795 p[enclen++] = a->bits >> 8;
796 p[enclen++] = a->bits;
797 memcpy( p + enclen, a->data, a->bytes );
798 enclen += a->bytes;
800 enclen += 20;
801 sk->enclen = enclen;
802 sk->protect.s2k = s2k;
803 sk->protect.algo = CDK_CIPHER_3DES;
804 sk->protect.ivlen = cdk_cipher_get_algo_blklen( sk->protect.algo );
805 gcry_randomize( sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM );
806 hd = cdk_cipher_open( sk->protect.algo, 1,
807 dek->key, dek->keylen,
808 sk->protect.iv, sk->protect.ivlen );
809 if( !hd ) {
810 cdk_free( p );
811 return CDK_Gcry_Error;
814 md = cdk_md_open( CDK_MD_SHA1, GCRY_CIPHER_SECURE );
815 if( !md ) {
816 cdk_cipher_close( hd );
817 cdk_free( p );
818 return CDK_Gcry_Error;
820 sk->protect.sha1chk = 1;
821 sk->is_protected = 1;
822 sk->csum = 0;
823 cdk_md_write( md, p, enclen - 20 );
824 cdk_md_final( md );
825 memcpy( p + enclen - 20, cdk_md_read( md, 0 ), 20 );
826 cdk_md_close( md );
827 rc = cdk_cipher_encrypt( hd, p, p, enclen );
828 cdk_cipher_close( hd );
829 cdk_dek_free( dek );
830 return rc;
835 * cdk_pk_from_secret_key:
836 * @sk: the secret key
837 * @ret_pk: the new public key
839 * Create a new public key from a secret key.
841 cdk_error_t
842 cdk_pk_from_secret_key( cdk_pkt_seckey_t sk, cdk_pkt_pubkey_t* ret_pk )
844 if( !sk )
845 return CDK_Inv_Value;
846 return _cdk_copy_pubkey( ret_pk, sk->pk );
851 cdk_pk_revoke_import( cdk_keydb_hd_t db, const char * revcert )
853 /* due to the fact the keydb code can't insert or modify packets
854 it is not possible to handle this step yet */
855 return 0;
860 cdk_pk_revoke_create( cdk_pkt_seckey_t sk, int code, const char * inf,
861 char ** ret_revcert )
863 cdk_md_hd_t md;
864 cdk_subpkt_t node;
865 cdk_pkt_signature_t sig;
866 char * p = NULL, * dat;
867 int n;
869 if( !sk || !ret_revcert )
870 return CDK_Inv_Value;
871 if( code < 0 || code > 3 )
872 return CDK_Inv_Value;
874 sig = cdk_calloc( 1, sizeof * sig );
875 if( !sig )
876 return CDK_Out_Of_Core;
877 _cdk_sig_create( sk->pk, sig );
878 n = 1;
879 if( inf ) {
880 n += strlen( p );
881 p = cdk_utf8_encode( inf );
883 dat = cdk_calloc( 1, n+1 );
884 if( !dat ) {
885 _cdk_free_signature( sig );
886 return CDK_Out_Of_Core;
888 dat[0] = code;
889 if( inf )
890 memcpy( dat+1, p, strlen( p ) );
891 cdk_free( p );
893 node = cdk_subpkt_new( n );
894 if( node ) {
895 cdk_subpkt_init( node, CDK_SIGSUBPKT_REVOC_REASON, dat, n );
896 cdk_subpkt_add( sig->hashed, node );
898 cdk_free( dat );
900 md = cdk_md_open( CDK_MD_SHA1, 0 );
901 if( !md ) {
902 _cdk_free_signature( sig );
903 return CDK_Gcry_Error;
905 _cdk_hash_pubkey( sk->pk, md, 0 );
906 _cdk_free_signature( sig );
907 return 0;
912 _cdk_sk_get_csum( cdk_pkt_seckey_t sk )
914 u16 csum = 0, i;
916 if( !sk )
917 return 0;
918 for( i = 0; i < cdk_pk_get_nskey( sk->pubkey_algo ); i++ )
919 csum += checksum_mpi( sk->mpi[i] );
920 return csum;
925 cdk_pk_get_fingerprint( cdk_pkt_pubkey_t pk, byte * fpr )
927 cdk_md_hd_t hd;
928 int md_algo;
929 int dlen = 0;
931 if( !pk || !fpr )
932 return CDK_Inv_Value;
934 if( pk->version < 4 && is_RSA( pk->pubkey_algo ) )
935 md_algo = CDK_MD_MD5; /* special */
936 else
937 md_algo = pk->version < 4 ? CDK_MD_RMD160 : CDK_MD_SHA1;
938 dlen = cdk_md_get_algo_dlen( md_algo );
939 hd = cdk_md_open( md_algo, 0 );
940 if( !hd )
941 return CDK_Gcry_Error;
942 _cdk_hash_pubkey( pk, hd, 1 );
943 cdk_md_final( hd );
944 memcpy( fpr, cdk_md_read( hd, md_algo ), dlen );
945 cdk_md_close( hd );
946 if( dlen == 16 )
947 memset( fpr + 16, 0, 4 );
948 return 0;
953 cdk_pk_fingerprint_get_keyid( const byte * fpr, size_t fprlen, u32 * keyid )
955 u32 lowbits = 0;
957 /* in this case we say the key is a V3 RSA key and we can't
958 use the fingerprint to get the keyid. */
959 if( fpr && fprlen == 16 )
960 return 0;
961 else if( keyid && fpr ) {
962 keyid[0] = _cdk_buftou32( fpr + 12 );
963 keyid[1] = _cdk_buftou32( fpr + 16 );
964 lowbits = keyid[1];
966 else if( fpr )
967 lowbits = _cdk_buftou32( fpr + 16 );
968 return lowbits;
973 cdk_pk_get_keyid( cdk_pkt_pubkey_t pk, u32 * keyid )
975 u32 lowbits = 0;
976 byte buf[24];
978 if( pk &&( !pk->keyid[0] || !pk->keyid[1] ) ) {
979 if( pk->version < 4 && is_RSA( pk->pubkey_algo ) ) {
980 size_t n = pk->mpi[0]->bytes;
981 const byte * p = pk->mpi[0]->data + 2;
982 pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5];
983 pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1];
985 else if( pk->version == 4 ) {
986 cdk_pk_get_fingerprint( pk, buf );
987 pk->keyid[0] = _cdk_buftou32( buf + 12 );
988 pk->keyid[1] = _cdk_buftou32( buf + 16 );
991 lowbits = pk ? pk->keyid[1] : 0;
992 if( keyid && pk ) {
993 keyid[0] = pk->keyid[0];
994 keyid[1] = pk->keyid[1];
996 return lowbits;
1001 cdk_sk_get_keyid( cdk_pkt_seckey_t sk, u32 * keyid )
1003 u32 lowbits = 0;
1005 if( sk && sk->pk ) {
1006 lowbits = cdk_pk_get_keyid( sk->pk, keyid );
1007 sk->keyid[0] = sk->pk->keyid[0];
1008 sk->keyid[1] = sk->pk->keyid[1];
1010 return lowbits;
1015 cdk_sig_get_keyid( cdk_pkt_signature_t sig, u32 * keyid )
1017 u32 lowbits = sig ? sig->keyid[1] : 0;
1019 if( keyid && sig ) {
1020 keyid[0] = sig->keyid[0];
1021 keyid[1] = sig->keyid[1];
1023 return lowbits;
1028 _cdk_pkt_get_keyid( cdk_packet_t pkt, u32 * keyid )
1030 u32 lowbits;
1032 if( !pkt )
1033 return 0;
1035 switch( pkt->pkttype ) {
1036 case CDK_PKT_PUBLIC_KEY:
1037 case CDK_PKT_PUBLIC_SUBKEY:
1038 lowbits = cdk_pk_get_keyid( pkt->pkt.public_key, keyid );
1039 break;
1041 case CDK_PKT_SECRET_KEY:
1042 case CDK_PKT_SECRET_SUBKEY:
1043 lowbits = cdk_sk_get_keyid( pkt->pkt.secret_key, keyid );
1044 break;
1046 case CDK_PKT_SIGNATURE:
1047 lowbits = cdk_sig_get_keyid( pkt->pkt.signature, keyid );
1048 break;
1050 default:
1051 lowbits = 0;
1053 return lowbits;
1058 _cdk_pkt_get_fingerprint( cdk_packet_t pkt, byte * fpr )
1060 if( !pkt || !fpr )
1061 return CDK_Inv_Value;
1063 switch( pkt->pkttype ) {
1064 case CDK_PKT_PUBLIC_KEY:
1065 case CDK_PKT_PUBLIC_SUBKEY:
1066 return cdk_pk_get_fingerprint( pkt->pkt.public_key, fpr );
1068 case CDK_PKT_SECRET_KEY:
1069 case CDK_PKT_SECRET_SUBKEY:
1070 return cdk_pk_get_fingerprint( pkt->pkt.secret_key->pk, fpr );
1072 default:
1073 return CDK_Inv_Packet;
1075 return 0;
1079 * cdk_pubkey_to_sexp:
1080 * @pk: the public key
1081 * @sexp: where to store the S-expression
1082 * @len: the length of sexp
1084 * Convert a public key to an S-expression. sexp is allocated by this
1085 * function, but you have to cdk_free() it yourself. The S-expression
1086 * is stored in canonical format as used by libgcrypt
1087 * (GCRYSEXP_FMT_CANON).
1090 cdk_error_t
1091 cdk_pubkey_to_sexp (cdk_pkt_pubkey_t pk, char **sexp, size_t * len)
1093 int rc;
1094 char *buf;
1095 size_t sexp_len;
1096 gcry_sexp_t pk_sexp;
1098 if (!pk || !sexp)
1099 return CDK_Inv_Value;
1101 rc = pubkey_to_sexp (&pk_sexp, pk);
1102 if (rc)
1103 return rc;
1105 sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
1106 if (!sexp_len)
1108 return CDK_Gcry_Error;
1111 buf = (char *) cdk_malloc (sexp_len);
1112 if (!buf)
1114 gcry_sexp_release (pk_sexp);
1115 return CDK_Out_Of_Core;
1118 sexp_len =
1119 gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
1121 gcry_sexp_release (pk_sexp);
1123 if (!sexp_len)
1125 cdk_free (buf);
1126 return CDK_Gcry_Error;
1129 if (len)
1130 *len = sexp_len;
1131 *sexp = buf;
1133 return CDK_Success;
1137 * cdk_seckey_to_sexp:
1138 * @sk: the secret key
1139 * @sexp: where to store the S-expression
1140 * @len: the length of sexp
1142 * Convert a public key to an S-expression. sexp is allocated by this
1143 * function, but you have to cdk_free() it yourself. The S-expression
1144 * is stored in canonical format as used by libgcrypt
1145 * (GCRYSEXP_FMT_CANON).
1148 cdk_error_t
1149 cdk_seckey_to_sexp (cdk_pkt_seckey_t sk, char **sexp, size_t * len)
1151 int rc;
1152 char *buf;
1153 size_t sexp_len;
1154 gcry_sexp_t sk_sexp;
1156 if (!sk || !sexp)
1157 return CDK_Inv_Value;
1159 rc = seckey_to_sexp (&sk_sexp, sk);
1160 if (rc)
1161 return rc;
1163 sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
1164 if (!sexp_len)
1166 return CDK_Gcry_Error;
1169 buf = (char *) cdk_malloc (sexp_len);
1170 if (!buf)
1172 gcry_sexp_release (sk_sexp);
1173 return CDK_Out_Of_Core;
1176 sexp_len =
1177 gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
1179 gcry_sexp_release (sk_sexp);
1181 if (!sexp_len)
1183 cdk_free (buf);
1184 return CDK_Gcry_Error;
1187 if (len)
1188 *len = sexp_len;
1189 *sexp = buf;
1191 return CDK_Success;