1
/* pubkey.c - Public key API
2
* Copyright (C) 2007 Free Software Foundation, Inc.
3
* Copyright (C) 2002, 2003, 2007 Timo Schulz
5
* This file is part of OpenCDK.
7
* OpenCDK 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 2 of the License, or
10
* (at your option) any later version.
12
* OpenCDK 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.
28
/* Convert the given secret key into a gcrypt SEXP object. */
30
seckey_to_sexp (gcry_sexp_t *r_skey, cdk_seckey_t sk)
32
gcry_sexp_t sexp = NULL;
33
gcry_mpi_t *mpk = NULL, *msk = NULL;
38
if (!r_skey || !sk || !sk->pk)
46
if (is_RSA (sk->pubkey_algo))
48
fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))";
49
err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
50
msk[0], msk[1], msk[2], msk[3]);
52
else if (is_ELG (sk->pubkey_algo))
54
fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))";
55
err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1],
58
else if (is_DSA (sk->pubkey_algo))
60
fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))";
61
err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], mpk[2],
67
return map_gcry_error (err);
73
/* Convert the given public key to a gcrypt SEXP object. */
75
pubkey_to_sexp (gcry_sexp_t *r_key_sexp, cdk_pubkey_t pk)
79
const char *fmt = NULL;
82
if (!r_key_sexp || !pk)
86
if (is_RSA (pk->pubkey_algo))
88
fmt = "(public-key(openpgp-rsa(n%m)(e%m)))";
89
err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1]);
91
rc = map_gcry_error (err);
93
else if (is_ELG (pk->pubkey_algo))
95
fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))";
96
err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2]);
98
rc = map_gcry_error (err);
100
else if (is_DSA (pk->pubkey_algo))
102
fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))";
103
err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2], m[3]);
105
rc = map_gcry_error (err);
114
enckey_to_sexp (gcry_sexp_t *r_sexp, gcry_mpi_t esk)
119
return CDK_Inv_Value;
120
err = gcry_sexp_build (r_sexp, NULL, "%m", esk);
122
return map_gcry_error (err);
128
digest_to_sexp (gcry_sexp_t *r_md_sexp, int digest_algo,
129
const byte *md, size_t mdlen)
134
if (!r_md_sexp || !md)
135
return CDK_Inv_Value;
138
mdlen = gcry_md_get_algo_dlen (digest_algo);
142
err = gcry_mpi_scan (&m, GCRYMPI_FMT_USG, md, mdlen, &mdlen);
144
return map_gcry_error (err);
146
err = gcry_sexp_build (r_md_sexp, NULL, "%m", m);
147
gcry_mpi_release (m);
149
return map_gcry_error (err);
155
sexp_to_mpi (gcry_sexp_t sexp, const char *val, gcry_mpi_t *ret_buf)
159
if (!sexp || !val || !ret_buf)
160
return CDK_Inv_Value;
162
list = gcry_sexp_find_token (sexp, val, 0);
164
return CDK_Inv_Value;
166
*ret_buf = gcry_sexp_nth_mpi (list, 1, 0);
167
gcry_sexp_release (list);
169
return CDK_Inv_Value;
175
sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp)
178
return CDK_Inv_Value;
180
/* ElGamal signatures are not supported any longer. */
181
if (is_ELG (sig->pubkey_algo))
183
_cdk_log_debug ("sexp_to_sig: unsupported signature type (ElGamal)\n");
184
return CDK_Not_Implemented;
187
if (is_RSA (sig->pubkey_algo))
188
return sexp_to_mpi (sexp, "s", &sig->mpi[0]);
189
else if (is_DSA (sig->pubkey_algo))
193
rc = sexp_to_mpi (sexp, "r", &sig->mpi[0]);
195
rc = sexp_to_mpi (sexp, "s", &sig->mpi[1]);
203
sig_to_sexp (gcry_sexp_t *r_sig_sexp, cdk_pkt_signature_t sig)
209
if (!r_sig_sexp || !sig)
210
return CDK_Inv_Value;
211
if (is_ELG (sig->pubkey_algo))
212
return CDK_Not_Implemented;
215
if (is_RSA (sig->pubkey_algo))
217
fmt = "(sig-val(openpgp-rsa(s%m)))";
218
err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0]);
220
rc = map_gcry_error (err);
222
else if (is_DSA (sig->pubkey_algo))
224
fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))";
225
err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0], sig->mpi[1]);
227
rc = map_gcry_error (err);
236
sexp_to_pubenc (cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp)
239
return CDK_Inv_Value;
241
if (is_RSA (enc->pubkey_algo))
242
return sexp_to_mpi (sexp, "a", &enc->mpi[0]);
243
else if (is_ELG (enc->pubkey_algo))
245
cdk_error_t rc = sexp_to_mpi (sexp, "a", &enc->mpi[0]);
247
rc = sexp_to_mpi (sexp, "b", &enc->mpi[1]);
255
pubenc_to_sexp (gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc)
257
gcry_sexp_t sexp = NULL;
262
return CDK_Inv_Value;
265
if (is_RSA (enc->pubkey_algo))
267
fmt = "(enc-val(openpgp-rsa((a%m))))";
268
err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0]);
270
else if (is_ELG (enc->pubkey_algo))
272
fmt = "(enc-val(openpgp-elg((a%m)(b%m))))";
273
err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0], enc->mpi[1]);
278
return map_gcry_error (err);
285
is_unprotected (cdk_seckey_t sk)
287
if (sk->is_protected && !sk->mpi[0])
295
* @pk: the public key
296
* @pke: the public key encrypted packet
297
* @esk: the actual session key
299
* Encrypt the session key in @esk and write its encrypted content
300
* into the @pke struct.
303
cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke,
306
gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL;
310
if (!pk || !esk || !pke)
311
return CDK_Inv_Value;
313
if (!KEY_CAN_ENCRYPT (pk->pubkey_algo))
316
rc = enckey_to_sexp (&s_data, esk);
318
rc = pubkey_to_sexp (&s_pkey, pk);
321
err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
323
return map_gcry_error (err);
326
rc = sexp_to_pubenc (pke, s_ciph);
328
gcry_sexp_release (s_data);
329
gcry_sexp_release (s_pkey);
330
gcry_sexp_release (s_ciph);
337
* @sk: the secret key
338
* @pke: public key encrypted packet
339
* @r_sk: the object to store the plain session key
341
* Decrypt the encrypted session key from @pke into @r_sk.
344
cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke,
347
gcry_sexp_t s_data = NULL, s_skey = NULL, s_plain = NULL;
351
if (!sk || !r_sk || !pke)
352
return CDK_Inv_Value;
354
if (!is_unprotected (sk))
358
rc = seckey_to_sexp (&s_skey, sk);
362
rc = pubenc_to_sexp (&s_data, pke);
365
gcry_sexp_release (s_skey);
369
err = gcry_pk_decrypt (&s_plain, s_data, s_skey);
371
rc = map_gcry_error (err);
373
*r_sk = gcry_sexp_nth_mpi (s_plain, 0, 0);
375
gcry_sexp_release (s_data);
376
gcry_sexp_release (s_skey);
377
gcry_sexp_release (s_plain);
386
* @md: the message digest
388
* Sign the message digest from @md and write the result into @sig.
391
cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, const byte *md)
393
gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL;
400
if (!sk || !sk->pk || !sig || !md)
401
return CDK_Inv_Value;
403
if (!is_unprotected (sk))
406
if (!KEY_CAN_SIGN (sig->pubkey_algo))
409
nbits = cdk_pk_get_nbits (sk->pk);
410
rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, sk->pk->pubkey_algo, md,
411
sig->digest_algo, nbits);
415
rc = seckey_to_sexp (&s_skey, sk);
417
rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen);
421
gcry_sexp_release (s_skey);
425
err = gcry_pk_sign (&s_sig, s_hash, s_skey);
427
rc = map_gcry_error (err);
430
rc = sexp_to_sig (sig, s_sig);
433
sig->digest_start[0] = md[0];
434
sig->digest_start[1] = md[1];
438
gcry_sexp_release (s_skey);
439
gcry_sexp_release (s_hash);
440
gcry_sexp_release (s_sig);
448
* @pk: the public key
450
* @md: the message digest
452
* Verify the signature in @sig and compare it with the message digest in @md.
455
cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte *md)
457
gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL;
462
if (!pk || !sig || !md)
463
return CDK_Inv_Value;
465
rc = pubkey_to_sexp (&s_pkey, pk);
469
rc = sig_to_sexp (&s_sig, sig);
473
rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md,
474
sig->digest_algo, cdk_pk_get_nbits (pk));
478
rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen);
482
if (gcry_pk_verify (s_sig, s_hash, s_pkey))
486
gcry_sexp_release (s_sig);
487
gcry_sexp_release (s_hash);
488
gcry_sexp_release (s_pkey);
496
* @pk: the public key
498
* Return the length of the public key in bits.
499
* The meaning of length is actually the size of the 'prime'
500
* object in the key. For RSA keys the modulus, for ElG/DSA
501
* the size of the public prime.
504
cdk_pk_get_nbits (cdk_pubkey_t pk)
506
if (!pk || !pk->mpi[0])
508
return gcry_mpi_get_nbits (pk->mpi[0]);
514
* @algo: The public key algorithm.
516
* Return the number of multiprecison integer forming an public
517
* key with the given algorithm.
520
cdk_pk_get_npkey (int algo)
525
algo = 20; /* FIXME: libgcrypt returns 0 for 16 */
526
if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &bytes))
534
* @algo: the public key algorithm
536
* Return the number of multiprecision integers forming an
537
* secret key with the given algorithm.
540
cdk_pk_get_nskey (int algo)
544
if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &bytes))
546
bytes -= cdk_pk_get_npkey (algo);
553
* @algo: the public key algorithm
555
* Return the number of MPIs a signature consists of.
558
cdk_pk_get_nsig (int algo)
562
if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &bytes))
570
* @algo: the public key algorithm
572
* Return the number of MPI's the encrypted data consists of.
575
cdk_pk_get_nenc (int algo)
579
if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NENCR, NULL, &bytes))
586
_cdk_pk_algo_usage (int algo)
590
/* The ElGamal sign+encrypt algorithm is not supported any longer. */
593
case CDK_PK_RSA : usage = CDK_KEY_USG_SIGN | CDK_KEY_USG_ENCR; break;
594
case CDK_PK_RSA_E: usage = CDK_KEY_USG_ENCR; break;
595
case CDK_PK_RSA_S: usage = CDK_KEY_USG_SIGN; break;
596
case CDK_PK_ELG_E: usage = CDK_KEY_USG_ENCR; break;
597
case CDK_PK_DSA : usage = CDK_KEY_USG_SIGN; break;
605
mpi_to_buffer (gcry_mpi_t a, byte *buf, size_t buflen,
606
size_t *r_nwritten, size_t *r_nbits)
610
if (!a || !buf || !r_nwritten)
611
return CDK_Inv_Value;
613
nbits = gcry_mpi_get_nbits (a);
616
if ((nbits+7)/8+2 > buflen)
617
return CDK_Too_Short;
618
*r_nwritten = (nbits+7)/8+2;
619
if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, buflen, r_nwritten, a))
620
return CDK_Wrong_Format;
628
* @idx: index of the MPI to retrieve
629
* @buf: buffer to hold the raw data
630
* @r_nwritten: output how large the raw data is
631
* @r_nbits: size of the MPI in bits.
633
* Return the MPI with the given index of the public key.
636
cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx,
637
byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
639
if (!pk || !r_nwritten)
640
return CDK_Inv_Value;
641
if (idx > cdk_pk_get_npkey (pk->pubkey_algo))
642
return CDK_Inv_Value;
643
return mpi_to_buffer (pk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
650
* @idx: index of the MPI to retrieve
651
* @buf: buffer to hold the raw data
652
* @r_nwritten: output length of the raw data
653
* @r_nbits: length of the MPI data in bits.
655
* Return the MPI of the given secret key with the
656
* index @idx. It is important to check if the key
657
* is protected and thus no real MPI data will be returned then.
660
cdk_sk_get_mpi (cdk_pkt_seckey_t sk, size_t idx,
661
byte *buf, size_t buflen, size_t *r_nwritten, size_t *r_nbits)
663
if (!sk || !r_nwritten)
664
return CDK_Inv_Value;
665
if (idx > cdk_pk_get_nskey (sk->pubkey_algo))
666
return CDK_Inv_Value;
667
return mpi_to_buffer (sk->mpi[idx], buf, buflen, r_nwritten, r_nbits);
672
checksum_mpi (gcry_mpi_t m)
674
byte buf[MAX_MPI_BYTES+2];
681
if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), &nread, m))
683
for (i=0; i < nread; i++)
691
* @sk: the secret key
692
* @pw: the passphrase
694
* Unprotect the given secret key with the passphrase.
697
cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw)
700
cdk_dek_t dek = NULL;
703
size_t ndata, nbits, nbytes;
704
int i, dlen, pos = 0, nskey;
709
return CDK_Inv_Value;
711
nskey = cdk_pk_get_nskey (sk->pubkey_algo);
712
if (!sk->is_protected)
715
for (i = 0; i < nskey; i++)
716
chksum += checksum_mpi (sk->mpi[i]);
717
if (chksum != sk->csum)
718
return CDK_Chksum_Error;
721
rc = cdk_dek_from_passphrase (&dek, sk->protect.algo,
722
sk->protect.s2k, 0, pw);
725
err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB,
726
GCRY_CIPHER_ENABLE_SYNC);
728
err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
730
err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
734
return map_gcry_error (err);
738
if (sk->version == 4)
741
data = cdk_salloc (ndata, 1);
743
return CDK_Out_Of_Core;
744
gcry_cipher_decrypt (hd, data, ndata, sk->encdata, ndata);
745
if (sk->protect.sha1chk)
747
/* This is the new SHA1 checksum method to detect tampering
748
with the key as used by the Klima/Rosa attack */
751
dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
755
return CDK_Inv_Packet;
761
gcry_md_hash_buffer (GCRY_MD_SHA1,
762
mdcheck, data, ndata-dlen);
763
if (!memcmp (mdcheck, data + ndata - dlen, dlen))
764
chksum = 0; /* Digest does match */
769
for (i = 0; i < ndata - 2; i++)
771
sk->csum = data[ndata - 2] << 8 | data[ndata - 1];
773
if (sk->csum == chksum)
775
for (i = 0; i < nskey; i++)
777
nbits = data[pos] << 8 | data[pos + 1];
779
if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, data,
780
(nbits+7)/8+2, &nbytes))
782
wipemem (data, sk->enclen);
784
return CDK_Wrong_Format;
786
gcry_mpi_set_flag (sk->mpi[i], GCRYMPI_FLAG_SECURE);
787
pos += (nbits+7)/8+2;
790
wipemem (data, sk->enclen);
795
byte buf[MAX_MPI_BYTES+2];
798
for (i = 0; i < nskey; i++)
800
gcry_cipher_sync (hd);
801
gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf),
802
&nbytes, sk->mpi[i]);
803
gcry_cipher_decrypt (hd, buf+2, nbytes-2, NULL, 0);
804
gcry_mpi_release (sk->mpi[i]);
805
if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP,
806
buf, nbytes, &nbytes))
807
return CDK_Wrong_Format;
808
chksum += checksum_mpi (sk->mpi[i]);
811
gcry_cipher_close (hd);
812
if (chksum != sk->csum)
813
return CDK_Chksum_Error;
814
sk->is_protected = 0;
821
* @sk: the secret key
822
* @pw: the passphrase to use
824
* Protect the given secret key with a passphrase.
827
cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pw)
829
gcry_cipher_hd_t hd = NULL;
830
cdk_dek_t dek = NULL;
832
byte *p = NULL, buf[MAX_MPI_BYTES+2];
833
size_t enclen = 0, nskey, i, nbytes;
834
size_t dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
838
nskey = cdk_pk_get_nskey (sk->pubkey_algo);
842
rc = cdk_s2k_new (&s2k, CDK_S2K_ITERSALTED, GCRY_MD_SHA256, NULL);
844
rc = cdk_dek_from_passphrase (&dek, GCRY_CIPHER_AES, s2k, 1, pw);
851
for (i = 0; i < nskey; i++)
854
enclen += (gcry_mpi_get_nbits (sk->mpi[i])+7)/8;
856
p = sk->encdata = cdk_calloc (1, enclen + dlen + 1);
860
return CDK_Out_Of_Core;
864
for (i = 0; i < nskey; i++)
866
if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf,
867
DIM (buf), &nbytes, sk->mpi[i]))
871
return CDK_Wrong_Format;
873
memcpy (p + enclen, buf, nbytes);
879
sk->protect.s2k = s2k;
880
sk->protect.algo = GCRY_CIPHER_AES;
881
sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo);
882
gcry_randomize (sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM);
883
err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB,
884
GCRY_CIPHER_ENABLE_SYNC);
888
rc = map_gcry_error (err);
892
err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
894
err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
898
rc = map_gcry_error (err);
902
sk->protect.sha1chk = 1;
903
sk->is_protected = 1;
906
gcry_md_hash_buffer (GCRY_MD_SHA1, buf, p, enclen-dlen);
907
memcpy (p + enclen - dlen, buf, dlen);
908
gcry_cipher_encrypt (hd, p, enclen, NULL, 0);
910
/* FIXME: We should release all MPI's and set the elements to NULL. */
913
gcry_cipher_close (hd);
919
* cdk_pk_from_secret_key:
920
* @sk: the secret key
921
* @ret_pk: the new public key
923
* Create a new public key from a secret key.
926
cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t *ret_pk)
929
return CDK_Inv_Value;
930
return _cdk_copy_pubkey (ret_pk, sk->pk);
934
#if 0 /* FIXME: Code is not finished yet. */
936
cdk_pk_revoke_cert_create (cdk_pkt_seckey_t sk, int code, const char *inf,
941
cdk_pkt_signature_t sig;
942
char *p = NULL, *dat;
947
if (!sk || !ret_revcert)
948
return CDK_Inv_Value;
949
if(code < 0 || code > 3)
950
return CDK_Inv_Value;
952
sig = cdk_calloc (1, sizeof *sig);
954
return CDK_Out_Of_Core;
955
_cdk_sig_create (sk->pk, sig);
960
p = cdk_utf8_encode (inf);
962
dat = cdk_calloc (1, n+1);
965
_cdk_free_signature (sig);
966
return CDK_Out_Of_Core;
970
memcpy (dat+1, p, strlen (p));
973
node = cdk_subpkt_new (n);
976
cdk_subpkt_init (node, CDK_SIGSUBPKT_REVOC_REASON, dat, n);
977
cdk_subpkt_add (sig->hashed, node);
981
err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
983
rc = map_gcry_error (err);
985
_cdk_hash_pubkey (sk->pk, md, 0);
986
_cdk_free_signature (sig);
993
_cdk_sk_get_csum (cdk_pkt_seckey_t sk)
999
for (i = 0; i < cdk_pk_get_nskey (sk->pubkey_algo); i++)
1000
csum += checksum_mpi (sk->mpi[i]);
1006
* cdk_pk_get_fingerprint:
1007
* @pk: the public key
1008
* @fpr: the buffer to hold the fingerprint
1010
* Return the fingerprint of the given public key.
1011
* The buffer must be at least 20 octets.
1012
* This function should be considered deprecated and
1013
* the new cdk_pk_to_fingerprint() should be used whenever
1014
* possible to avoid overflows.
1017
cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr)
1025
return CDK_Inv_Value;
1027
if (pk->version < 4 && is_RSA (pk->pubkey_algo))
1028
md_algo = GCRY_MD_MD5; /* special */
1030
md_algo = GCRY_MD_SHA1;
1031
dlen = gcry_md_get_algo_dlen (md_algo);
1032
err = gcry_md_open (&hd, md_algo, 0);
1034
return map_gcry_error (err);
1035
_cdk_hash_pubkey (pk, hd, 1);
1037
memcpy (fpr, gcry_md_read (hd, md_algo), dlen);
1040
memset (fpr + 16, 0, 4);
1046
* cdk_pk_to_fingerprint:
1047
* @pk: the public key
1048
* @fprbuf: buffer to save the fingerprint
1049
* @fprbuflen: buffer size
1050
* @r_nout: actual length of the fingerprint.
1052
* Calculate a fingerprint of the given key and
1053
* return it in the given byte array.
1056
cdk_pk_to_fingerprint (cdk_pubkey_t pk,
1057
byte *fprbuf, size_t fprbuflen, size_t *r_nout)
1063
return CDK_Inv_Value;
1065
if (pk->version < 4)
1070
/* Only return the required buffer size for the fingerprint. */
1071
if (!fprbuf && !fprbuflen && r_nout)
1073
*r_nout = key_fprlen;
1077
if (!fprbuf || key_fprlen > fprbuflen)
1078
return CDK_Too_Short;
1080
err = cdk_pk_get_fingerprint (pk, fprbuf);
1082
*r_nout = key_fprlen;
1089
* cdk_pk_fingerprint_get_keyid:
1090
* @fpr: the key fingerprint
1091
* @fprlen: the length of the fingerprint
1093
* Derive the key ID from the key fingerprint.
1094
* For version 3 keys, this is not working.
1097
cdk_pk_fingerprint_get_keyid (const byte *fpr, size_t fprlen, u32 *keyid)
1101
/* In this case we say the key is a V3 RSA key and we can't
1102
use the fingerprint to get the keyid. */
1103
if (fpr && fprlen == 16)
1109
else if (keyid && fpr)
1111
keyid[0] = _cdk_buftou32 (fpr + 12);
1112
keyid[1] = _cdk_buftou32 (fpr + 16);
1116
lowbits = _cdk_buftou32 (fpr + 16);
1123
* @pk: the public key
1124
* @keyid: buffer to store the key ID
1126
* Calculate the key ID of the given public key.
1129
cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid)
1134
if (pk && (!pk->keyid[0] || !pk->keyid[1]))
1136
if (pk->version < 4 && is_RSA (pk->pubkey_algo))
1138
byte p[MAX_MPI_BYTES];
1141
gcry_mpi_print (GCRYMPI_FMT_USG, p, MAX_MPI_BYTES, &n, pk->mpi[0]);
1142
pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5];
1143
pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1];
1145
else if (pk->version == 4)
1147
cdk_pk_get_fingerprint (pk, buf);
1148
pk->keyid[0] = _cdk_buftou32 (buf + 12);
1149
pk->keyid[1] = _cdk_buftou32 (buf + 16);
1152
lowbits = pk ? pk->keyid[1] : 0;
1155
keyid[0] = pk->keyid[0];
1156
keyid[1] = pk->keyid[1];
1165
* @sk: the secret key
1166
* @keyid: buffer to hold the key ID
1168
* Calculate the key ID of the secret key, actually the public key.
1171
cdk_sk_get_keyid (cdk_pkt_seckey_t sk, u32 *keyid)
1177
lowbits = cdk_pk_get_keyid (sk->pk, keyid);
1178
sk->keyid[0] = sk->pk->keyid[0];
1179
sk->keyid[1] = sk->pk->keyid[1];
1187
* cdk_sig_get_keyid:
1188
* @sig: the signature
1189
* @keyid: buffer to hold the key ID
1191
* Retrieve the key ID from the given signature.
1194
cdk_sig_get_keyid (cdk_pkt_signature_t sig, u32 *keyid)
1196
u32 lowbits = sig ? sig->keyid[1] : 0;
1200
keyid[0] = sig->keyid[0];
1201
keyid[1] = sig->keyid[1];
1207
/* Return the key ID from the given packet.
1208
If this is not possible, 0 is returned */
1210
_cdk_pkt_get_keyid (cdk_packet_t pkt, u32 *keyid)
1217
switch (pkt->pkttype)
1219
case CDK_PKT_PUBLIC_KEY:
1220
case CDK_PKT_PUBLIC_SUBKEY:
1221
lowbits = cdk_pk_get_keyid (pkt->pkt.public_key, keyid);
1224
case CDK_PKT_SECRET_KEY:
1225
case CDK_PKT_SECRET_SUBKEY:
1226
lowbits = cdk_sk_get_keyid (pkt->pkt.secret_key, keyid);
1229
case CDK_PKT_SIGNATURE:
1230
lowbits = cdk_sig_get_keyid (pkt->pkt.signature, keyid);
1242
/* Get the fingerprint of the packet if possible. */
1244
_cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr)
1247
return CDK_Inv_Value;
1249
switch (pkt->pkttype)
1251
case CDK_PKT_PUBLIC_KEY:
1252
case CDK_PKT_PUBLIC_SUBKEY:
1253
return cdk_pk_get_fingerprint (pkt->pkt.public_key, fpr);
1255
case CDK_PKT_SECRET_KEY:
1256
case CDK_PKT_SECRET_SUBKEY:
1257
return cdk_pk_get_fingerprint (pkt->pkt.secret_key->pk, fpr);
1260
return CDK_Inv_Mode;
1267
* cdk_pubkey_to_sexp:
1268
* @pk: the public key
1269
* @sexp: where to store the S-expression
1270
* @len: the length of sexp
1272
* Convert a public key to an S-expression. sexp is allocated by this
1273
* function, but you have to cdk_free() it yourself. The S-expression
1274
* is stored in canonical format as used by libgcrypt
1275
* (GCRYSEXP_FMT_CANON).
1278
cdk_pubkey_to_sexp (cdk_pubkey_t pk, char **sexp, size_t * len)
1282
gcry_sexp_t pk_sexp;
1286
return CDK_Inv_Value;
1288
rc = pubkey_to_sexp (&pk_sexp, pk);
1292
sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
1294
return CDK_Wrong_Format;
1296
buf = (char *)cdk_malloc (sexp_len);
1299
gcry_sexp_release (pk_sexp);
1300
return CDK_Out_Of_Core;
1303
sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
1304
gcry_sexp_release (pk_sexp);
1308
return CDK_Wrong_Format;
1319
* cdk_seckey_to_sexp:
1320
* @sk: the secret key
1321
* @sexp: where to store the S-expression
1322
* @len: the length of sexp
1324
* Convert a public key to an S-expression. sexp is allocated by this
1325
* function, but you have to cdk_free() it yourself. The S-expression
1326
* is stored in canonical format as used by libgcrypt
1327
* (GCRYSEXP_FMT_CANON).
1330
cdk_seckey_to_sexp (cdk_pkt_seckey_t sk, char **sexp, size_t * len)
1334
gcry_sexp_t sk_sexp;
1338
return CDK_Inv_Value;
1340
rc = seckey_to_sexp (&sk_sexp, sk);
1344
sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, NULL, 0);
1346
return CDK_Wrong_Format;
1348
buf = (char *) cdk_malloc (sexp_len);
1351
gcry_sexp_release (sk_sexp);
1352
return CDK_Out_Of_Core;
1355
sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len);
1356
gcry_sexp_release (sk_sexp);
1360
return CDK_Wrong_Format;