2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 /* This file contains the functions needed for RSA/DSA public key
26 * encryption and signatures.
29 #include <gnutls_int.h>
30 #include <gnutls_mpi.h>
31 #include <gnutls_pk.h>
32 #include <gnutls_errors.h>
33 #include <gnutls_datum.h>
34 #include <gnutls_global.h>
35 #include <gnutls_num.h>
37 #include <x509/x509_int.h>
38 #include <x509/common.h>
41 static int _gnutls_pk_encrypt (int algo
, mpi_t
* resarr
, mpi_t data
,
42 mpi_t
* pkey
, int pkey_len
);
43 static int _gnutls_pk_sign (int algo
, mpi_t
* data
, mpi_t hash
,
45 static int _gnutls_pk_verify (int algo
, mpi_t hash
, mpi_t
* data
,
47 static int _gnutls_pk_decrypt (int algo
, mpi_t
* resarr
, mpi_t data
,
51 /* Do PKCS-1 RSA encryption.
52 * params is modulus, public exp.
55 _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t
* ciphertext
,
56 const gnutls_datum_t
* plaintext
,
57 mpi_t
* params
, unsigned params_len
,
67 mod_bits
= _gnutls_mpi_get_nbits (params
[0]);
69 if (mod_bits
% 8 != 0)
72 if (plaintext
->size
> k
- 11)
75 return GNUTLS_E_PK_ENCRYPTION_FAILED
;
78 edata
= gnutls_malloc (k
);
82 return GNUTLS_E_MEMORY_ERROR
;
85 /* EB = 00||BT||PS||00||D
86 * (use block type 'btype')
91 psize
= k
- 3 - plaintext
->size
;
97 /* using public key */
98 if (params_len
< RSA_PUBLIC_PARAMS
)
102 return GNUTLS_E_INTERNAL_ERROR
;
105 ret
= _gnutls_rnd (RND_RANDOM
, ps
, psize
);
112 for (i
= 0; i
< psize
; i
++)
115 ret
= _gnutls_rnd (RND_RANDOM
, &ps
[i
], 1);
125 /* using private key */
127 if (params_len
< RSA_PRIVATE_PARAMS
)
131 return GNUTLS_E_INTERNAL_ERROR
;
134 for (i
= 0; i
< psize
; i
++)
140 return GNUTLS_E_INTERNAL_ERROR
;
144 memcpy (&ps
[psize
+ 1], plaintext
->data
, plaintext
->size
);
146 if (_gnutls_mpi_scan_nz (&m
, edata
, &k
) != 0)
150 return GNUTLS_E_MPI_SCAN_FAILED
;
154 if (btype
== 2) /* encrypt */
155 ret
= _gnutls_pk_encrypt (GCRY_PK_RSA
, &res
, m
, params
, params_len
);
157 ret
= _gnutls_pk_sign (GCRY_PK_RSA
, &res
, m
, params
, params_len
);
159 _gnutls_mpi_release (&m
);
167 _gnutls_mpi_print (NULL
, &psize
, res
);
180 { /* psize > k !!! */
181 /* This is an impossible situation */
183 _gnutls_mpi_release (&res
);
184 return GNUTLS_E_INTERNAL_ERROR
;
187 ciphertext
->data
= gnutls_malloc (psize
);
188 if (ciphertext
->data
== NULL
)
191 _gnutls_mpi_release (&res
);
192 return GNUTLS_E_MEMORY_ERROR
;
194 _gnutls_mpi_print (&ciphertext
->data
[pad
], &psize
, res
);
195 for (i
= 0; i
< pad
; i
++)
196 ciphertext
->data
[i
] = 0;
198 ciphertext
->size
= k
;
200 _gnutls_mpi_release (&res
);
206 /* Do PKCS-1 RSA decryption.
207 * params is modulus, public exp., private key
208 * Can decrypt block type 1 and type 2 packets.
211 _gnutls_pkcs1_rsa_decrypt (gnutls_datum_t
* plaintext
,
212 const gnutls_datum_t
* ciphertext
,
213 mpi_t
* params
, unsigned params_len
,
220 size_t esize
, mod_bits
;
222 mod_bits
= _gnutls_mpi_get_nbits (params
[0]);
224 if (mod_bits
% 8 != 0)
227 esize
= ciphertext
->size
;
232 return GNUTLS_E_PK_DECRYPTION_FAILED
;
235 if (_gnutls_mpi_scan_nz (&c
, ciphertext
->data
, &esize
) != 0)
238 return GNUTLS_E_MPI_SCAN_FAILED
;
241 /* we can use btype to see if the private key is
245 ret
= _gnutls_pk_decrypt (GCRY_PK_RSA
, &res
, c
, params
, params_len
);
248 ret
= _gnutls_pk_encrypt (GCRY_PK_RSA
, &res
, c
, params
, params_len
);
250 _gnutls_mpi_release (&c
);
258 _gnutls_mpi_print (NULL
, &esize
, res
);
259 edata
= gnutls_malloc (esize
+ 1);
263 _gnutls_mpi_release (&res
);
264 return GNUTLS_E_MEMORY_ERROR
;
266 _gnutls_mpi_print (&edata
[1], &esize
, res
);
268 _gnutls_mpi_release (&res
);
270 /* EB = 00||BT||PS||00||D
271 * (use block type 'btype')
273 * From now on, return GNUTLS_E_DECRYPTION_FAILED on errors, to
274 * avoid attacks similar to the one described by Bleichenbacher in:
275 * "Chosen Ciphertext Attacks against Protocols Based on RSA
276 * Encryption Standard PKCS #1".
283 if (edata
[0] != 0 || edata
[1] != btype
)
287 return GNUTLS_E_DECRYPTION_FAILED
;
290 ret
= GNUTLS_E_DECRYPTION_FAILED
;
294 for (i
= 2; i
< esize
; i
++)
304 for (i
= 2; i
< esize
; i
++)
306 if (edata
[i
] == 0 && i
> 2)
311 if (edata
[i
] != 0xff)
313 _gnutls_handshake_log ("PKCS #1 padding error");
314 /* PKCS #1 padding error. Don't use
315 GNUTLS_E_PKCS1_WRONG_PAD here. */
331 return GNUTLS_E_DECRYPTION_FAILED
;
334 if (_gnutls_sset_datum (plaintext
, &edata
[i
], esize
- i
) < 0)
338 return GNUTLS_E_MEMORY_ERROR
;
348 _gnutls_rsa_verify (const gnutls_datum_t
* vdata
,
349 const gnutls_datum_t
* ciphertext
, mpi_t
* params
,
350 int params_len
, int btype
)
353 gnutls_datum_t plain
;
356 /* decrypt signature */
358 _gnutls_pkcs1_rsa_decrypt (&plain
, ciphertext
, params
, params_len
,
365 if (plain
.size
!= vdata
->size
)
368 _gnutls_free_datum (&plain
);
369 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;
372 if (memcmp (plain
.data
, vdata
->data
, plain
.size
) != 0)
375 _gnutls_free_datum (&plain
);
376 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;
379 _gnutls_free_datum (&plain
);
384 /* encodes the Dss-Sig-Value structure
387 encode_ber_rs (gnutls_datum_t
* sig_value
, mpi_t r
, mpi_t s
)
393 asn1_create_element (_gnutls_get_gnutls_asn (),
394 "GNUTLS.DSASignatureValue",
395 &sig
)) != ASN1_SUCCESS
)
398 return _gnutls_asn2err (result
);
401 result
= _gnutls_x509_write_int (sig
, "r", r
, 1);
405 asn1_delete_structure (&sig
);
409 result
= _gnutls_x509_write_int (sig
, "s", s
, 1);
413 asn1_delete_structure (&sig
);
419 result
= _gnutls_x509_der_encode (sig
, "", sig_value
, 0);
421 asn1_delete_structure (&sig
);
433 /* Do DSA signature calculation. params is p, q, g, y, x in that order.
436 _gnutls_dsa_sign (gnutls_datum_t
* signature
,
437 const gnutls_datum_t
* hash
, mpi_t
* params
,
446 { /* SHA1 or better only */
448 return GNUTLS_E_PK_SIGN_FAILED
;
451 if (_gnutls_mpi_scan_nz (&mdata
, hash
->data
, &k
) != 0)
454 return GNUTLS_E_MPI_SCAN_FAILED
;
457 ret
= _gnutls_pk_sign (GCRY_PK_DSA
, rs
, mdata
, params
, params_len
);
458 /* rs[0], rs[1] now hold r,s */
459 _gnutls_mpi_release (&mdata
);
467 ret
= encode_ber_rs (signature
, rs
[0], rs
[1]);
470 _gnutls_mpi_release (&rs
[0]);
471 _gnutls_mpi_release (&rs
[1]);
476 return GNUTLS_E_MEMORY_ERROR
;
482 /* decodes the Dss-Sig-Value structure
485 decode_ber_rs (const gnutls_datum_t
* sig_value
, mpi_t
* r
, mpi_t
* s
)
491 asn1_create_element (_gnutls_get_gnutls_asn (),
492 "GNUTLS.DSASignatureValue",
493 &sig
)) != ASN1_SUCCESS
)
496 return _gnutls_asn2err (result
);
499 result
= asn1_der_decoding (&sig
, sig_value
->data
, sig_value
->size
, NULL
);
500 if (result
!= ASN1_SUCCESS
)
503 asn1_delete_structure (&sig
);
504 return _gnutls_asn2err (result
);
507 result
= _gnutls_x509_read_int (sig
, "r", r
);
511 asn1_delete_structure (&sig
);
515 result
= _gnutls_x509_read_int (sig
, "s", s
);
519 _gnutls_mpi_release (s
);
520 asn1_delete_structure (&sig
);
524 asn1_delete_structure (&sig
);
529 /* params is p, q, g, y in that order
532 _gnutls_dsa_verify (const gnutls_datum_t
* vdata
,
533 const gnutls_datum_t
* sig_value
, mpi_t
* params
,
542 if (vdata
->size
!= 20)
545 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;
548 if (decode_ber_rs (sig_value
, &rs
[0], &rs
[1]) != 0)
551 return GNUTLS_E_MPI_SCAN_FAILED
;
555 if (_gnutls_mpi_scan_nz (&mdata
, vdata
->data
, &k
) != 0)
558 _gnutls_mpi_release (&rs
[0]);
559 _gnutls_mpi_release (&rs
[1]);
560 return GNUTLS_E_MPI_SCAN_FAILED
;
563 /* decrypt signature */
564 ret
= _gnutls_pk_verify (GCRY_PK_DSA
, mdata
, rs
, params
, params_len
);
565 _gnutls_mpi_release (&mdata
);
566 _gnutls_mpi_release (&rs
[0]);
567 _gnutls_mpi_release (&rs
[1]);
579 /* this is taken from gnupg
583 * Emulate our old PK interface here - sometime in the future we might
584 * change the internal design to directly fit to libgcrypt.
587 _gnutls_pk_encrypt (int algo
, mpi_t
* resarr
, mpi_t data
,
588 mpi_t
* pkey
, int pkey_len
)
590 gcry_sexp_t s_ciph
, s_data
, s_pkey
;
593 /* make a sexp from pkey */
598 rc
= gcry_sexp_build (&s_pkey
, NULL
,
599 "(public-key(rsa(n%m)(e%m)))",
605 return GNUTLS_E_INTERNAL_ERROR
;
611 return GNUTLS_E_INTERNAL_ERROR
;
614 /* put the data into a simple list */
615 if (gcry_sexp_build (&s_data
, NULL
, "%m", data
))
618 gcry_sexp_release (s_pkey
);
619 return GNUTLS_E_INTERNAL_ERROR
;
622 /* pass it to libgcrypt */
623 rc
= gcry_pk_encrypt (&s_ciph
, s_data
, s_pkey
);
624 gcry_sexp_release (s_data
);
625 gcry_sexp_release (s_pkey
);
630 return GNUTLS_E_PK_ENCRYPTION_FAILED
;
634 { /* add better error handling or make gnupg use S-Exp directly */
635 gcry_sexp_t list
= gcry_sexp_find_token (s_ciph
, "a", 0);
639 gcry_sexp_release (s_ciph
);
640 return GNUTLS_E_INTERNAL_ERROR
;
643 resarr
[0] = gcry_sexp_nth_mpi (list
, 1, 0);
644 gcry_sexp_release (list
);
646 if (resarr
[0] == NULL
)
649 gcry_sexp_release (s_ciph
);
650 return GNUTLS_E_INTERNAL_ERROR
;
654 gcry_sexp_release (s_ciph
);
659 _gnutls_pk_decrypt (int algo
, mpi_t
* resarr
, mpi_t data
, mpi_t
* pkey
,
662 gcry_sexp_t s_plain
, s_data
, s_pkey
;
665 /* make a sexp from pkey */
670 rc
= gcry_sexp_build (&s_pkey
, NULL
,
671 "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
672 pkey
[0], pkey
[1], pkey
[2], pkey
[3],
678 return GNUTLS_E_INTERNAL_ERROR
;
684 return GNUTLS_E_INTERNAL_ERROR
;
687 /* put the data into a simple list */
688 if (gcry_sexp_build (&s_data
, NULL
, "(enc-val(rsa(a%m)))", data
))
691 gcry_sexp_release (s_pkey
);
692 return GNUTLS_E_INTERNAL_ERROR
;
695 /* pass it to libgcrypt */
696 rc
= gcry_pk_decrypt (&s_plain
, s_data
, s_pkey
);
697 gcry_sexp_release (s_data
);
698 gcry_sexp_release (s_pkey
);
703 return GNUTLS_E_PK_DECRYPTION_FAILED
;
707 { /* add better error handling or make gnupg use S-Exp directly */
708 resarr
[0] = gcry_sexp_nth_mpi (s_plain
, 0, 0);
710 if (resarr
[0] == NULL
)
713 gcry_sexp_release (s_plain
);
714 return GNUTLS_E_INTERNAL_ERROR
;
718 gcry_sexp_release (s_plain
);
723 /* in case of DSA puts into data, r,s
726 _gnutls_pk_sign (int algo
, mpi_t
* data
, mpi_t hash
, mpi_t
* pkey
,
729 gcry_sexp_t s_hash
, s_key
, s_sig
;
732 /* make a sexp from pkey */
737 rc
= gcry_sexp_build (&s_key
, NULL
,
738 "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
739 pkey
[0], pkey
[1], pkey
[2], pkey
[3], pkey
[4]);
748 rc
= gcry_sexp_build (&s_key
, NULL
,
749 "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
750 pkey
[0], pkey
[1], pkey
[2], pkey
[3],
760 return GNUTLS_E_INTERNAL_ERROR
;
766 return GNUTLS_E_INTERNAL_ERROR
;
769 /* put the data into a simple list */
770 if (gcry_sexp_build (&s_hash
, NULL
, "%m", hash
))
773 return GNUTLS_E_INTERNAL_ERROR
;
776 /* pass it to libgcrypt */
777 rc
= gcry_pk_sign (&s_sig
, s_hash
, s_key
);
778 gcry_sexp_release (s_hash
);
779 gcry_sexp_release (s_key
);
784 return GNUTLS_E_PK_SIGN_FAILED
;
791 if (algo
== GCRY_PK_DSA
)
793 list
= gcry_sexp_find_token (s_sig
, "r", 0);
797 gcry_sexp_release (s_sig
);
798 return GNUTLS_E_INTERNAL_ERROR
;
801 data
[0] = gcry_sexp_nth_mpi (list
, 1, 0);
802 gcry_sexp_release (list
);
804 list
= gcry_sexp_find_token (s_sig
, "s", 0);
808 gcry_sexp_release (s_sig
);
809 return GNUTLS_E_INTERNAL_ERROR
;
812 data
[1] = gcry_sexp_nth_mpi (list
, 1, 0);
813 gcry_sexp_release (list
);
817 list
= gcry_sexp_find_token (s_sig
, "s", 0);
821 gcry_sexp_release (s_sig
);
822 return GNUTLS_E_INTERNAL_ERROR
;
825 data
[0] = gcry_sexp_nth_mpi (list
, 1, 0);
826 gcry_sexp_release (list
);
830 gcry_sexp_release (s_sig
);
836 _gnutls_pk_verify (int algo
, mpi_t hash
, mpi_t
* data
,
837 mpi_t
* pkey
, int pkey_len
)
839 gcry_sexp_t s_sig
, s_hash
, s_pkey
;
842 /* make a sexp from pkey */
847 rc
= gcry_sexp_build (&s_pkey
, NULL
,
848 "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))",
849 pkey
[0], pkey
[1], pkey
[2], pkey
[3]);
853 rc
= gcry_sexp_build (&s_pkey
, NULL
,
854 "(public-key(rsa(n%m)(e%m)))",
860 return GNUTLS_E_INTERNAL_ERROR
;
866 return GNUTLS_E_INTERNAL_ERROR
;
869 /* put the data into a simple list */
870 if (gcry_sexp_build (&s_hash
, NULL
, "%m", hash
))
873 gcry_sexp_release (s_pkey
);
874 return GNUTLS_E_INTERNAL_ERROR
;
880 rc
= gcry_sexp_build (&s_sig
, NULL
,
881 "(sig-val(dsa(r%m)(s%m)))", data
[0], data
[1]);
884 rc
= gcry_sexp_build (&s_sig
, NULL
, "(sig-val(rsa(s%m)))", data
[0]);
889 gcry_sexp_release (s_pkey
);
890 gcry_sexp_release (s_hash
);
891 return GNUTLS_E_INTERNAL_ERROR
;
897 gcry_sexp_release (s_pkey
);
898 gcry_sexp_release (s_hash
);
899 return GNUTLS_E_INTERNAL_ERROR
;
902 rc
= gcry_pk_verify (s_sig
, s_hash
, s_pkey
);
904 gcry_sexp_release (s_sig
);
905 gcry_sexp_release (s_hash
);
906 gcry_sexp_release (s_pkey
);
911 return GNUTLS_E_PK_SIG_VERIFY_FAILED
;