1 /* pubkey.c - Public key API
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
6 * This file is part of OpenCDK.
8 * The OpenCDK library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
26 #include <gnutls_int.h>
27 #include <gnutls_datum.h>
28 #include <gnutls_pk.h>
29 #include <gnutls_sig.h>
30 #include <x509/common.h>
35 /* This function gets the signature parameters and encodes
36 * them into a way for _gnutls_pk_verify to use.
39 sig_to_datum (gnutls_datum_t
* r_sig
, cdk_pkt_signature_t sig
)
48 if (is_RSA (sig
->pubkey_algo
))
50 err
= _gnutls_mpi_dprint (sig
->mpi
[0], r_sig
);
52 rc
= map_gnutls_error (err
);
54 else if (is_DSA (sig
->pubkey_algo
))
56 err
= _gnutls_encode_ber_rs (r_sig
, sig
->mpi
[0], sig
->mpi
[1]);
58 rc
= map_gnutls_error (err
);
69 * @md: the message digest
71 * Verify the signature in @sig and compare it with the message digest in @md.
74 cdk_pk_verify (cdk_pubkey_t pk
, cdk_pkt_signature_t sig
, const byte
* md
)
76 gnutls_datum_t s_sig
= { NULL
, 0}, di
= {NULL
, 0};
82 gnutls_pk_params_st params
;
84 if (!pk
|| !sig
|| !md
)
90 if (is_DSA (pk
->pubkey_algo
))
92 else if (is_RSA (pk
->pubkey_algo
))
100 rc
= sig_to_datum (&s_sig
, sig
);
107 rc
= _gnutls_set_datum (&di
, md
, _gnutls_hash_get_algo_len (sig
->digest_algo
));
110 rc
= gnutls_assert_val(CDK_Out_Of_Core
);
114 rc
= pk_prepare_hash (algo
, sig
->digest_algo
, &di
);
117 rc
= gnutls_assert_val(CDK_General_Error
);
121 params
.params_nr
= cdk_pk_get_npkey (pk
->pubkey_algo
);
122 for (i
= 0; i
< params
.params_nr
; i
++)
123 params
.params
[i
] = pk
->mpi
[i
];
125 ret
= _gnutls_pk_verify (algo
, &di
, &s_sig
, ¶ms
);
130 rc
= map_gnutls_error (ret
);
137 _gnutls_free_datum (&s_sig
);
138 _gnutls_free_datum (&di
);
146 * @pk: the public key
148 * Return the length of the public key in bits.
149 * The meaning of length is actually the size of the 'prime'
150 * object in the key. For RSA keys the modulus, for ElG/DSA
151 * the size of the public prime.
154 cdk_pk_get_nbits (cdk_pubkey_t pk
)
156 if (!pk
|| !pk
->mpi
[0])
158 return _gnutls_mpi_get_nbits (pk
->mpi
[0]);
164 * @algo: The public key algorithm.
166 * Return the number of multiprecison integer forming an public
167 * key with the given algorithm.
170 cdk_pk_get_npkey (int algo
)
173 return RSA_PUBLIC_PARAMS
;
174 else if (is_DSA (algo
))
175 return DSA_PUBLIC_PARAMS
;
176 else if (is_ELG (algo
))
188 * @algo: the public key algorithm
190 * Return the number of multiprecision integers forming an
191 * secret key with the given algorithm.
194 cdk_pk_get_nskey (int algo
)
199 ret
= RSA_PRIVATE_PARAMS
- 2; /* we don't have exp1 and exp2 */
200 else if (is_DSA (algo
))
201 ret
= DSA_PRIVATE_PARAMS
;
202 else if (is_ELG (algo
))
210 ret
-= cdk_pk_get_npkey (algo
);
217 * @algo: the public key algorithm
219 * Return the number of MPIs a signature consists of.
222 cdk_pk_get_nsig (int algo
)
226 else if (is_DSA (algo
))
235 * @algo: the public key algorithm
237 * Return the number of MPI's the encrypted data consists of.
240 cdk_pk_get_nenc (int algo
)
244 else if (is_ELG (algo
))
252 _cdk_pk_algo_usage (int algo
)
256 /* The ElGamal sign+encrypt algorithm is not supported any longer. */
260 usage
= CDK_KEY_USG_SIGN
| CDK_KEY_USG_ENCR
;
263 usage
= CDK_KEY_USG_ENCR
;
266 usage
= CDK_KEY_USG_SIGN
;
269 usage
= CDK_KEY_USG_ENCR
;
272 usage
= CDK_KEY_USG_SIGN
;
280 /* You can use a NULL buf to get the output size only
283 mpi_to_buffer (bigint_t a
, byte
* buf
, size_t buflen
,
284 size_t * r_nwritten
, size_t * r_nbits
)
289 if (!a
|| !r_nwritten
)
292 return CDK_Inv_Value
;
295 nbits
= _gnutls_mpi_get_nbits (a
);
300 *r_nwritten
= (nbits
+ 7) / 8 + 2;
302 if ((nbits
+ 7) / 8 + 2 > buflen
)
303 return CDK_Too_Short
;
305 *r_nwritten
= buflen
;
306 err
= _gnutls_mpi_print (a
, buf
, r_nwritten
);
310 return map_gnutls_error (err
);
320 * @idx: index of the MPI to retrieve
321 * @buf: buffer to hold the raw data
322 * @r_nwritten: output how large the raw data is
323 * @r_nbits: size of the MPI in bits.
325 * Return the MPI with the given index of the public key.
328 cdk_pk_get_mpi (cdk_pubkey_t pk
, size_t idx
,
329 byte
* buf
, size_t buflen
, size_t * r_nwritten
,
332 if (!pk
|| !r_nwritten
)
333 return CDK_Inv_Value
;
335 if ((ssize_t
) idx
> cdk_pk_get_npkey (pk
->pubkey_algo
))
336 return CDK_Inv_Value
;
337 return mpi_to_buffer (pk
->mpi
[idx
], buf
, buflen
, r_nwritten
, r_nbits
);
344 * @idx: index of the MPI to retrieve
345 * @buf: buffer to hold the raw data
346 * @r_nwritten: output length of the raw data
347 * @r_nbits: length of the MPI data in bits.
349 * Return the MPI of the given secret key with the
350 * index @idx. It is important to check if the key
351 * is protected and thus no real MPI data will be returned then.
354 cdk_sk_get_mpi (cdk_pkt_seckey_t sk
, size_t idx
,
355 byte
* buf
, size_t buflen
, size_t * r_nwritten
,
358 if (!sk
|| !r_nwritten
)
359 return CDK_Inv_Value
;
361 if ((ssize_t
) idx
> cdk_pk_get_nskey (sk
->pubkey_algo
))
362 return CDK_Inv_Value
;
363 return mpi_to_buffer (sk
->mpi
[idx
], buf
, buflen
, r_nwritten
, r_nbits
);
368 checksum_mpi (bigint_t m
)
370 byte buf
[MAX_MPI_BYTES
+ 2];
378 if (_gnutls_mpi_print_pgp (m
, buf
, &nread
) < 0)
380 for (i
= 0; i
< nread
; i
++)
386 * cdk_pk_from_secret_key:
387 * @sk: the secret key
388 * @ret_pk: the new public key
390 * Create a new public key from a secret key.
393 cdk_pk_from_secret_key (cdk_pkt_seckey_t sk
, cdk_pubkey_t
* ret_pk
)
396 return CDK_Inv_Value
;
397 return _cdk_copy_pubkey (ret_pk
, sk
->pk
);
402 _cdk_sk_get_csum (cdk_pkt_seckey_t sk
)
408 for (i
= 0; i
< cdk_pk_get_nskey (sk
->pubkey_algo
); i
++)
409 csum
+= checksum_mpi (sk
->mpi
[i
]);
415 * cdk_pk_get_fingerprint:
416 * @pk: the public key
417 * @fpr: the buffer to hold the fingerprint
419 * Return the fingerprint of the given public key.
420 * The buffer must be at least 20 octets.
421 * This function should be considered deprecated and
422 * the new cdk_pk_to_fingerprint() should be used whenever
423 * possible to avoid overflows.
426 cdk_pk_get_fingerprint (cdk_pubkey_t pk
, byte
* fpr
)
434 return CDK_Inv_Value
;
436 if (pk
->version
< 4 && is_RSA (pk
->pubkey_algo
))
437 md_algo
= GNUTLS_DIG_MD5
; /* special */
439 md_algo
= GNUTLS_DIG_SHA1
;
440 dlen
= _gnutls_hash_get_algo_len (md_algo
);
441 err
= _gnutls_hash_init (&hd
, md_algo
);
445 return map_gnutls_error (err
);
447 _cdk_hash_pubkey (pk
, &hd
, 1);
448 _gnutls_hash_deinit (&hd
, fpr
);
450 memset (fpr
+ 16, 0, 4);
456 * cdk_pk_to_fingerprint:
457 * @pk: the public key
458 * @fprbuf: buffer to save the fingerprint
459 * @fprbuflen: buffer size
460 * @r_nout: actual length of the fingerprint.
462 * Calculate a fingerprint of the given key and
463 * return it in the given byte array.
466 cdk_pk_to_fingerprint (cdk_pubkey_t pk
,
467 byte
* fprbuf
, size_t fprbuflen
, size_t * r_nout
)
473 return CDK_Inv_Value
;
480 /* Only return the required buffer size for the fingerprint. */
481 if (!fprbuf
&& !fprbuflen
&& r_nout
)
483 *r_nout
= key_fprlen
;
487 if (!fprbuf
|| key_fprlen
> fprbuflen
)
488 return CDK_Too_Short
;
490 err
= cdk_pk_get_fingerprint (pk
, fprbuf
);
492 *r_nout
= key_fprlen
;
499 * cdk_pk_fingerprint_get_keyid:
500 * @fpr: the key fingerprint
501 * @fprlen: the length of the fingerprint
503 * Derive the key ID from the key fingerprint.
504 * For version 3 keys, this is not working.
507 cdk_pk_fingerprint_get_keyid (const byte
* fpr
, size_t fprlen
, u32
* keyid
)
511 /* In this case we say the key is a V3 RSA key and we can't
512 use the fingerprint to get the keyid. */
513 if (fpr
&& fprlen
== 16)
519 else if (keyid
&& fpr
)
521 keyid
[0] = _cdk_buftou32 (fpr
+ 12);
522 keyid
[1] = _cdk_buftou32 (fpr
+ 16);
526 lowbits
= _cdk_buftou32 (fpr
+ 16);
533 * @pk: the public key
534 * @keyid: buffer to store the key ID
536 * Calculate the key ID of the given public key.
539 cdk_pk_get_keyid (cdk_pubkey_t pk
, u32
* keyid
)
544 if (pk
&& (!pk
->keyid
[0] || !pk
->keyid
[1]))
546 if (pk
->version
< 4 && is_RSA (pk
->pubkey_algo
))
548 byte p
[MAX_MPI_BYTES
];
552 _gnutls_mpi_print (pk
->mpi
[0], p
, &n
);
554 p
[n
- 8] << 24 | p
[n
- 7] << 16 | p
[n
- 6] << 8 | p
[n
- 5];
556 p
[n
- 4] << 24 | p
[n
- 3] << 16 | p
[n
- 2] << 8 | p
[n
- 1];
558 else if (pk
->version
== 4)
560 cdk_pk_get_fingerprint (pk
, buf
);
561 pk
->keyid
[0] = _cdk_buftou32 (buf
+ 12);
562 pk
->keyid
[1] = _cdk_buftou32 (buf
+ 16);
565 lowbits
= pk
? pk
->keyid
[1] : 0;
568 keyid
[0] = pk
->keyid
[0];
569 keyid
[1] = pk
->keyid
[1];
578 * @sk: the secret key
579 * @keyid: buffer to hold the key ID
581 * Calculate the key ID of the secret key, actually the public key.
584 cdk_sk_get_keyid (cdk_pkt_seckey_t sk
, u32
* keyid
)
590 lowbits
= cdk_pk_get_keyid (sk
->pk
, keyid
);
591 sk
->keyid
[0] = sk
->pk
->keyid
[0];
592 sk
->keyid
[1] = sk
->pk
->keyid
[1];
601 * @sig: the signature
602 * @keyid: buffer to hold the key ID
604 * Retrieve the key ID from the given signature.
607 cdk_sig_get_keyid (cdk_pkt_signature_t sig
, u32
* keyid
)
609 u32 lowbits
= sig
? sig
->keyid
[1] : 0;
613 keyid
[0] = sig
->keyid
[0];
614 keyid
[1] = sig
->keyid
[1];
620 /* Return the key ID from the given packet.
621 If this is not possible, 0 is returned */
623 _cdk_pkt_get_keyid (cdk_packet_t pkt
, u32
* keyid
)
630 switch (pkt
->pkttype
)
632 case CDK_PKT_PUBLIC_KEY
:
633 case CDK_PKT_PUBLIC_SUBKEY
:
634 lowbits
= cdk_pk_get_keyid (pkt
->pkt
.public_key
, keyid
);
637 case CDK_PKT_SECRET_KEY
:
638 case CDK_PKT_SECRET_SUBKEY
:
639 lowbits
= cdk_sk_get_keyid (pkt
->pkt
.secret_key
, keyid
);
642 case CDK_PKT_SIGNATURE
:
643 lowbits
= cdk_sig_get_keyid (pkt
->pkt
.signature
, keyid
);
655 /* Get the fingerprint of the packet if possible. */
657 _cdk_pkt_get_fingerprint (cdk_packet_t pkt
, byte
* fpr
)
660 return CDK_Inv_Value
;
662 switch (pkt
->pkttype
)
664 case CDK_PKT_PUBLIC_KEY
:
665 case CDK_PKT_PUBLIC_SUBKEY
:
666 return cdk_pk_get_fingerprint (pkt
->pkt
.public_key
, fpr
);
668 case CDK_PKT_SECRET_KEY
:
669 case CDK_PKT_SECRET_SUBKEY
:
670 return cdk_pk_get_fingerprint (pkt
->pkt
.secret_key
->pk
, fpr
);