Imported Upstream version 3.4.11
[platform/upstream/gnutls.git] / lib / gnutls_privkey.c
1 /*
2  * GnuTLS PKCS#11 support
3  * Copyright (C) 2010-2014 Free Software Foundation, Inc.
4  * Copyright (C) 2012-2014 Nikos Mavrogiannopoulos
5  * 
6  * Author: Nikos Mavrogiannopoulos
7  *
8  * The GnuTLS 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.
12  *
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.
17  *
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/>
20  */
21
22 #include <gnutls_int.h>
23 #include <gnutls/pkcs11.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <gnutls_errors.h>
27 #include <gnutls_datum.h>
28 #include <pkcs11_int.h>
29 #include <gnutls/abstract.h>
30 #include <gnutls_pk.h>
31 #include <x509_int.h>
32 #include <openpgp/openpgp_int.h>
33 #include <openpgp/gnutls_openpgp.h>
34 #include <gnutls_sig.h>
35 #include <algorithms.h>
36 #include <fips.h>
37 #include <system-keys.h>
38 #include "urls.h"
39 #include <abstract_int.h>
40
41 static int
42 _gnutls_privkey_sign_raw_data(gnutls_privkey_t key,
43                              unsigned flags,
44                              const gnutls_datum_t * data,
45                              gnutls_datum_t * signature);
46
47 /**
48  * gnutls_privkey_get_type:
49  * @key: should contain a #gnutls_privkey_t type
50  *
51  * This function will return the type of the private key. This is
52  * actually the type of the subsystem used to set this private key.
53  *
54  * Returns: a member of the #gnutls_privkey_type_t enumeration on
55  *   success, or a negative error code on error.
56  *
57  * Since: 2.12.0
58  **/
59 gnutls_privkey_type_t gnutls_privkey_get_type(gnutls_privkey_t key)
60 {
61         return key->type;
62 }
63
64 /**
65  * gnutls_privkey_get_pk_algorithm:
66  * @key: should contain a #gnutls_privkey_t type
67  * @bits: If set will return the number of bits of the parameters (may be NULL)
68  *
69  * This function will return the public key algorithm of a private
70  * key and if possible will return a number of bits that indicates
71  * the security parameter of the key.
72  *
73  * Returns: a member of the #gnutls_pk_algorithm_t enumeration on
74  *   success, or a negative error code on error.
75  *
76  * Since: 2.12.0
77  **/
78 int gnutls_privkey_get_pk_algorithm(gnutls_privkey_t key, unsigned int *bits)
79 {
80         switch (key->type) {
81 #ifdef ENABLE_OPENPGP
82         case GNUTLS_PRIVKEY_OPENPGP:
83                 return gnutls_openpgp_privkey_get_pk_algorithm(key->key.openpgp,
84                                                                bits);
85 #endif
86 #ifdef ENABLE_PKCS11
87         case GNUTLS_PRIVKEY_PKCS11:
88                 return gnutls_pkcs11_privkey_get_pk_algorithm(key->key.pkcs11,
89                                                               bits);
90 #endif
91         case GNUTLS_PRIVKEY_X509:
92                 if (bits)
93                         *bits =
94                             _gnutls_mpi_get_nbits(key->key.x509->
95                                                   params.params[0]);
96                 return gnutls_x509_privkey_get_pk_algorithm(key->key.x509);
97         case GNUTLS_PRIVKEY_EXT:
98                 if (bits)
99                         *bits = 0;
100                 return key->pk_algorithm;
101         default:
102                 gnutls_assert();
103                 return GNUTLS_E_INVALID_REQUEST;
104         }
105
106 }
107
108 static int
109 privkey_to_pubkey(gnutls_pk_algorithm_t pk,
110                   const gnutls_pk_params_st * priv, gnutls_pk_params_st * pub)
111 {
112         int ret;
113
114         pub->algo = priv->algo;
115         pub->flags = priv->flags;
116
117         switch (pk) {
118         case GNUTLS_PK_RSA:
119                 pub->params[0] = _gnutls_mpi_copy(priv->params[0]);
120                 pub->params[1] = _gnutls_mpi_copy(priv->params[1]);
121
122                 pub->params_nr = RSA_PUBLIC_PARAMS;
123
124                 if (pub->params[0] == NULL || pub->params[1] == NULL) {
125                         gnutls_assert();
126                         ret = GNUTLS_E_MEMORY_ERROR;
127                         goto cleanup;
128                 }
129
130                 break;
131         case GNUTLS_PK_DSA:
132                 pub->params[0] = _gnutls_mpi_copy(priv->params[0]);
133                 pub->params[1] = _gnutls_mpi_copy(priv->params[1]);
134                 pub->params[2] = _gnutls_mpi_copy(priv->params[2]);
135                 pub->params[3] = _gnutls_mpi_copy(priv->params[3]);
136
137                 pub->params_nr = DSA_PUBLIC_PARAMS;
138
139                 if (pub->params[0] == NULL || pub->params[1] == NULL ||
140                     pub->params[2] == NULL || pub->params[3] == NULL) {
141                         gnutls_assert();
142                         ret = GNUTLS_E_MEMORY_ERROR;
143                         goto cleanup;
144                 }
145
146                 break;
147         case GNUTLS_PK_EC:
148                 pub->params[ECC_X] = _gnutls_mpi_copy(priv->params[ECC_X]);
149                 pub->params[ECC_Y] = _gnutls_mpi_copy(priv->params[ECC_Y]);
150
151                 pub->params_nr = ECC_PUBLIC_PARAMS;
152
153                 if (pub->params[ECC_X] == NULL || pub->params[ECC_Y] == NULL) {
154                         gnutls_assert();
155                         ret = GNUTLS_E_MEMORY_ERROR;
156                         goto cleanup;
157                 }
158
159                 break;
160         default:
161                 gnutls_assert();
162                 return GNUTLS_E_INVALID_REQUEST;
163         }
164
165         return 0;
166  cleanup:
167         gnutls_pk_params_release(pub);
168         return ret;
169 }
170
171 /* Returns the public key of the private key (if possible)
172  */
173 int
174 _gnutls_privkey_get_mpis(gnutls_privkey_t key, gnutls_pk_params_st * params)
175 {
176         int ret;
177
178         switch (key->type) {
179 #ifdef ENABLE_OPENPGP
180         case GNUTLS_PRIVKEY_OPENPGP:
181                 {
182                         uint32_t kid[2];
183                         uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
184
185                         ret =
186                             gnutls_openpgp_privkey_get_preferred_key_id
187                             (key->key.openpgp, keyid);
188                         if (ret == 0) {
189                                 KEYID_IMPORT(kid, keyid);
190                                 ret =
191                                     _gnutls_openpgp_privkey_get_mpis
192                                     (key->key.openpgp, kid, params);
193                         } else
194                                 ret =
195                                     _gnutls_openpgp_privkey_get_mpis
196                                     (key->key.openpgp, NULL, params);
197
198                         if (ret < 0) {
199                                 gnutls_assert();
200                                 return ret;
201                         }
202                 }
203
204                 break;
205 #endif
206         case GNUTLS_PRIVKEY_X509:
207                 ret = _gnutls_pk_params_copy(params, &key->key.x509->params);
208                 break;
209 #ifdef ENABLE_PKCS11
210         case GNUTLS_PRIVKEY_PKCS11: {
211                 gnutls_pubkey_t pubkey;
212
213                 ret = _pkcs11_privkey_get_pubkey(key->key.pkcs11, &pubkey, 0);
214                 if (ret < 0)
215                         return gnutls_assert_val(ret);
216
217                 ret = _gnutls_pubkey_get_mpis(pubkey, params);
218                 gnutls_pubkey_deinit(pubkey);
219
220                 break;
221                 }
222 #endif
223         default:
224                 gnutls_assert();
225                 return GNUTLS_E_INVALID_REQUEST;
226         }
227
228         return ret;
229 }
230
231 int
232 _gnutls_privkey_get_public_mpis(gnutls_privkey_t key,
233                                 gnutls_pk_params_st * params)
234 {
235         int ret;
236         gnutls_pk_params_st tmp1;
237
238         gnutls_pk_params_init(&tmp1);
239
240         ret = _gnutls_privkey_get_mpis(key, &tmp1);
241         if (ret < 0)
242                 return gnutls_assert_val(ret);
243
244         ret = privkey_to_pubkey(key->pk_algorithm, &tmp1, params);
245
246         gnutls_pk_params_release(&tmp1);
247
248         if (ret < 0)
249                 gnutls_assert();
250
251         return ret;
252 }
253
254 /**
255  * gnutls_privkey_init:
256  * @key: A pointer to the type to be initialized
257  *
258  * This function will initialize a private key.
259  *
260  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
261  *   negative error value.
262  *
263  * Since: 2.12.0
264  **/
265 int gnutls_privkey_init(gnutls_privkey_t * key)
266 {
267         FAIL_IF_LIB_ERROR;
268
269         *key = gnutls_calloc(1, sizeof(struct gnutls_privkey_st));
270         if (*key == NULL) {
271                 gnutls_assert();
272                 return GNUTLS_E_MEMORY_ERROR;
273         }
274
275         return 0;
276 }
277
278 /**
279  * gnutls_privkey_deinit:
280  * @key: The key to be deinitialized
281  *
282  * This function will deinitialize a private key structure.
283  *
284  * Since: 2.12.0
285  **/
286 void gnutls_privkey_deinit(gnutls_privkey_t key)
287 {
288         if (key == NULL)
289                 return;
290
291         if (key->flags & GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
292             || key->flags & GNUTLS_PRIVKEY_IMPORT_COPY)
293                 switch (key->type) {
294 #ifdef ENABLE_OPENPGP
295                 case GNUTLS_PRIVKEY_OPENPGP:
296                         gnutls_openpgp_privkey_deinit(key->key.openpgp);
297                         break;
298 #endif
299 #ifdef ENABLE_PKCS11
300                 case GNUTLS_PRIVKEY_PKCS11:
301                         gnutls_pkcs11_privkey_deinit(key->key.pkcs11);
302                         break;
303 #endif
304                 case GNUTLS_PRIVKEY_X509:
305                         gnutls_x509_privkey_deinit(key->key.x509);
306                         break;
307                 case GNUTLS_PRIVKEY_EXT:
308                         if (key->key.ext.deinit_func != NULL)
309                                 key->key.ext.deinit_func(key,
310                                                          key->key.ext.userdata);
311                         break;
312                 default:
313                         break;
314                 }
315         gnutls_free(key);
316 }
317
318 /* will fail if the private key contains an actual key.
319  */
320 static int check_if_clean(gnutls_privkey_t key)
321 {
322         if (key->type != 0)
323                 return GNUTLS_E_INVALID_REQUEST;
324
325         return 0;
326 }
327
328 #ifdef ENABLE_PKCS11
329
330 /**
331  * gnutls_privkey_import_pkcs11:
332  * @pkey: The private key
333  * @key: The private key to be imported
334  * @flags: Flags for the import
335  *
336  * This function will import the given private key to the abstract
337  * #gnutls_privkey_t type.
338  *
339  * The #gnutls_pkcs11_privkey_t object must not be deallocated
340  * during the lifetime of this structure.
341  *
342  * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
343  * and %GNUTLS_PRIVKEY_IMPORT_COPY.
344  *
345  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
346  *   negative error value.
347  *
348  * Since: 2.12.0
349  **/
350 int
351 gnutls_privkey_import_pkcs11(gnutls_privkey_t pkey,
352                              gnutls_pkcs11_privkey_t key, unsigned int flags)
353 {
354         int ret;
355
356         ret = check_if_clean(pkey);
357         if (ret < 0) {
358                 gnutls_assert();
359                 return ret;
360         }
361
362         if (flags & GNUTLS_PRIVKEY_IMPORT_COPY)
363                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
364
365         pkey->key.pkcs11 = key;
366         pkey->type = GNUTLS_PRIVKEY_PKCS11;
367         pkey->pk_algorithm = gnutls_pkcs11_privkey_get_pk_algorithm(key, NULL);
368         pkey->flags = flags;
369
370         if (pkey->pin.data)
371                 gnutls_pkcs11_privkey_set_pin_function(key, pkey->pin.cb,
372                                                        pkey->pin.data);
373
374         return 0;
375 }
376
377 #if 0
378 /**
379  * gnutls_privkey_import_pkcs11_url:
380  * @key: A key of type #gnutls_pubkey_t
381  * @url: A PKCS 11 url
382  *
383  * This function will import a PKCS 11 private key to a #gnutls_private_key_t
384  * type.
385  *
386  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
387  *   negative error value.
388  *
389  * Since: 3.1.0
390  **/
391
392 int gnutls_privkey_import_pkcs11_url(gnutls_privkey_t key, const char *url)
393 {
394         int x;
395 }
396 #endif
397
398 static
399 int _gnutls_privkey_import_pkcs11_url(gnutls_privkey_t key, const char *url, unsigned flags)
400 {
401         gnutls_pkcs11_privkey_t pkey;
402         int ret;
403
404         ret = gnutls_pkcs11_privkey_init(&pkey);
405         if (ret < 0) {
406                 gnutls_assert();
407                 return ret;
408         }
409
410         if (key->pin.cb)
411                 gnutls_pkcs11_privkey_set_pin_function(pkey, key->pin.cb,
412                                                        key->pin.data);
413
414         ret = gnutls_pkcs11_privkey_import_url(pkey, url, flags);
415         if (ret < 0) {
416                 gnutls_assert();
417                 goto cleanup;
418         }
419
420         ret =
421             gnutls_privkey_import_pkcs11(key, pkey,
422                                          GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
423         if (ret < 0) {
424                 gnutls_assert();
425                 goto cleanup;
426         }
427
428         return 0;
429
430  cleanup:
431         gnutls_pkcs11_privkey_deinit(pkey);
432
433         return ret;
434 }
435
436 /**
437  * gnutls_privkey_export_pkcs11:
438  * @pkey: The private key
439  * @key: Location for the key to be exported.
440  *
441  * Converts the given abstract private key to a #gnutls_pkcs11_privkey_t
442  * type. The key must be of type %GNUTLS_PRIVKEY_PKCS11. The key
443  * returned in @key must be deinitialized with
444  * gnutls_pkcs11_privkey_deinit().
445  *
446  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
447  *   negative error value.
448  *
449  * Since: 3.4.0
450  */
451 int
452 gnutls_privkey_export_pkcs11(gnutls_privkey_t pkey,
453                              gnutls_pkcs11_privkey_t *key)
454 {
455         int ret;
456
457         if (pkey->type != GNUTLS_PRIVKEY_PKCS11) {
458                 gnutls_assert();
459                 return GNUTLS_E_INVALID_REQUEST;
460         }
461
462         ret = gnutls_pkcs11_privkey_init(key);
463         if (ret < 0)
464                 return gnutls_assert_val(ret);
465
466         ret = gnutls_pkcs11_privkey_cpy(*key, pkey->key.pkcs11);
467         if (ret < 0) {
468                 gnutls_pkcs11_privkey_deinit(*key);
469                 *key = NULL;
470
471                 return gnutls_assert_val(ret);
472         }
473
474         return 0;
475 }
476 #endif                          /* ENABLE_PKCS11 */
477
478 /**
479  * gnutls_privkey_import_ext:
480  * @pkey: The private key
481  * @pk: The public key algorithm
482  * @userdata: private data to be provided to the callbacks
483  * @sign_func: callback for signature operations
484  * @decrypt_func: callback for decryption operations
485  * @flags: Flags for the import
486  *
487  * This function will associate the given callbacks with the
488  * #gnutls_privkey_t type. At least one of the two callbacks
489  * must be non-null.
490  *
491  * See also gnutls_privkey_import_ext3().
492  *
493  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
494  *   negative error value.
495  *
496  * Since: 3.0
497  **/
498 int
499 gnutls_privkey_import_ext(gnutls_privkey_t pkey,
500                           gnutls_pk_algorithm_t pk,
501                           void *userdata,
502                           gnutls_privkey_sign_func sign_func,
503                           gnutls_privkey_decrypt_func decrypt_func,
504                           unsigned int flags)
505 {
506         return gnutls_privkey_import_ext2(pkey, pk, userdata, sign_func,
507                                           decrypt_func, NULL, flags);
508 }
509
510 /**
511  * gnutls_privkey_import_ext2:
512  * @pkey: The private key
513  * @pk: The public key algorithm
514  * @userdata: private data to be provided to the callbacks
515  * @sign_fn: callback for signature operations
516  * @decrypt_fn: callback for decryption operations
517  * @deinit_fn: a deinitialization function
518  * @flags: Flags for the import
519  *
520  * This function will associate the given callbacks with the
521  * #gnutls_privkey_t type. At least one of the two callbacks
522  * must be non-null. If a deinitialization function is provided
523  * then flags is assumed to contain %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE.
524  *
525  * Note that the signing function is supposed to "raw" sign data, i.e.,
526  * without any hashing or preprocessing. In case of RSA the DigestInfo
527  * will be provided, and the signing function is expected to do the PKCS #1
528  * 1.5 padding and the exponentiation.
529  *
530  * See also gnutls_privkey_import_ext3().
531  *
532  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
533  *   negative error value.
534  *
535  * Since: 3.1
536  **/
537 int
538 gnutls_privkey_import_ext2(gnutls_privkey_t pkey,
539                            gnutls_pk_algorithm_t pk,
540                            void *userdata,
541                            gnutls_privkey_sign_func sign_fn,
542                            gnutls_privkey_decrypt_func decrypt_fn,
543                            gnutls_privkey_deinit_func deinit_fn,
544                            unsigned int flags)
545 {
546         int ret;
547
548         ret = check_if_clean(pkey);
549         if (ret < 0) {
550                 gnutls_assert();
551                 return ret;
552         }
553
554         if (sign_fn == NULL && decrypt_fn == NULL)
555                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
556
557         pkey->key.ext.sign_func = sign_fn;
558         pkey->key.ext.decrypt_func = decrypt_fn;
559         pkey->key.ext.deinit_func = deinit_fn;
560         pkey->key.ext.userdata = userdata;
561         pkey->type = GNUTLS_PRIVKEY_EXT;
562         pkey->pk_algorithm = pk;
563         pkey->flags = flags;
564
565         /* Ensure gnutls_privkey_deinit() calls the deinit_func */
566         if (deinit_fn)
567                 pkey->flags |= GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
568
569         return 0;
570 }
571
572 /**
573  * gnutls_privkey_import_ext3:
574  * @pkey: The private key
575  * @userdata: private data to be provided to the callbacks
576  * @sign_fn: callback for signature operations
577  * @decrypt_fn: callback for decryption operations
578  * @deinit_fn: a deinitialization function
579  * @info_fn: returns info about the public key algorithm (should not be %NULL)
580  * @flags: Flags for the import
581  *
582  * This function will associate the given callbacks with the
583  * #gnutls_privkey_t type. At least one of the two callbacks
584  * must be non-null. If a deinitialization function is provided
585  * then flags is assumed to contain %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE.
586  *
587  * Note that the signing function is supposed to "raw" sign data, i.e.,
588  * without any hashing or preprocessing. In case of RSA the DigestInfo
589  * will be provided, and the signing function is expected to do the PKCS #1
590  * 1.5 padding and the exponentiation.
591  *
592  * The @info_fn must provide information on the algorithms supported by
593  * this private key, and should support the flags %GNUTLS_PRIVKEY_INFO_PK_ALGO and
594  * %GNUTLS_PRIVKEY_INFO_SIGN_ALGO. It must return -1 on unknown flags.
595  *
596  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
597  *   negative error value.
598  *
599  * Since: 3.4.0
600  **/
601 int
602 gnutls_privkey_import_ext3(gnutls_privkey_t pkey,
603                            void *userdata,
604                            gnutls_privkey_sign_func sign_fn,
605                            gnutls_privkey_decrypt_func decrypt_fn,
606                            gnutls_privkey_deinit_func deinit_fn,
607                            gnutls_privkey_info_func info_fn,
608                            unsigned int flags)
609 {
610         int ret;
611
612         ret = check_if_clean(pkey);
613         if (ret < 0) {
614                 gnutls_assert();
615                 return ret;
616         }
617
618         if (sign_fn == NULL && decrypt_fn == NULL)
619                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
620
621         if (info_fn == NULL)
622                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
623
624         pkey->key.ext.sign_func = sign_fn;
625         pkey->key.ext.decrypt_func = decrypt_fn;
626         pkey->key.ext.deinit_func = deinit_fn;
627         pkey->key.ext.info_func = info_fn;
628         pkey->key.ext.userdata = userdata;
629         pkey->type = GNUTLS_PRIVKEY_EXT;
630         pkey->flags = flags;
631
632         pkey->pk_algorithm = pkey->key.ext.info_func(pkey, GNUTLS_PRIVKEY_INFO_PK_ALGO, pkey->key.ext.userdata);
633
634         /* Ensure gnutls_privkey_deinit() calls the deinit_func */
635         if (deinit_fn)
636                 pkey->flags |= GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
637
638         return 0;
639 }
640
641 /**
642  * gnutls_privkey_import_x509:
643  * @pkey: The private key
644  * @key: The private key to be imported
645  * @flags: Flags for the import
646  *
647  * This function will import the given private key to the abstract
648  * #gnutls_privkey_t type.
649  *
650  * The #gnutls_x509_privkey_t object must not be deallocated
651  * during the lifetime of this structure.
652  *
653  * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
654  * and %GNUTLS_PRIVKEY_IMPORT_COPY.
655  *
656  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
657  *   negative error value.
658  *
659  * Since: 2.12.0
660  **/
661 int
662 gnutls_privkey_import_x509(gnutls_privkey_t pkey,
663                            gnutls_x509_privkey_t key, unsigned int flags)
664 {
665         int ret;
666
667         ret = check_if_clean(pkey);
668         if (ret < 0) {
669                 gnutls_assert();
670                 return ret;
671         }
672
673         if (flags & GNUTLS_PRIVKEY_IMPORT_COPY) {
674                 ret = gnutls_x509_privkey_init(&pkey->key.x509);
675                 if (ret < 0)
676                         return gnutls_assert_val(ret);
677
678                 ret = gnutls_x509_privkey_cpy(pkey->key.x509, key);
679                 if (ret < 0) {
680                         gnutls_x509_privkey_deinit(pkey->key.x509);
681                         return gnutls_assert_val(ret);
682                 }
683         } else
684                 pkey->key.x509 = key;
685
686         pkey->type = GNUTLS_PRIVKEY_X509;
687         pkey->pk_algorithm = gnutls_x509_privkey_get_pk_algorithm(key);
688         pkey->flags = flags;
689
690         return 0;
691 }
692
693 /**
694  * gnutls_privkey_export_x509:
695  * @pkey: The private key
696  * @key: Location for the key to be exported.
697  *
698  * Converts the given abstract private key to a #gnutls_x509_privkey_t
699  * type. The key must be of type %GNUTLS_PRIVKEY_X509. The key returned
700  * in @key must be deinitialized with gnutls_x509_privkey_deinit().
701  *
702  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
703  *   negative error value.
704  *
705  * Since: 3.4.0
706  */
707 int
708 gnutls_privkey_export_x509(gnutls_privkey_t pkey,
709                            gnutls_x509_privkey_t *key)
710 {
711         int ret;
712
713         if (pkey->type != GNUTLS_PRIVKEY_X509) {
714                 gnutls_assert();
715                 return GNUTLS_E_INVALID_REQUEST;
716         }
717
718         ret = gnutls_x509_privkey_init(key);
719         if (ret < 0)
720                 return gnutls_assert_val(ret);
721
722         ret = gnutls_x509_privkey_cpy(*key, pkey->key.x509);
723         if (ret < 0) {
724                 gnutls_x509_privkey_deinit(*key);
725                 *key = NULL;
726
727                 return gnutls_assert_val(ret);
728         }
729
730         return 0;
731 }
732
733 /**
734  * gnutls_privkey_generate:
735  * @pkey: The private key
736  * @algo: is one of the algorithms in #gnutls_pk_algorithm_t.
737  * @bits: the size of the modulus
738  * @flags: unused for now.  Must be 0.
739  *
740  * This function will generate a random private key. Note that this
741  * function must be called on an empty private key.
742  *
743  * Note that when generating an elliptic curve key, the curve
744  * can be substituted in the place of the bits parameter using the
745  * GNUTLS_CURVE_TO_BITS() macro.
746  *
747  * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits().
748  *
749  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
750  *   negative error value.
751  *
752  * Since: 3.3.0
753  **/
754 int
755 gnutls_privkey_generate(gnutls_privkey_t pkey,
756                         gnutls_pk_algorithm_t algo, unsigned int bits,
757                         unsigned int flags)
758 {
759         int ret;
760
761         ret = gnutls_x509_privkey_init(&pkey->key.x509);
762         if (ret < 0)
763                 return gnutls_assert_val(ret);
764
765         ret = gnutls_x509_privkey_generate(pkey->key.x509, algo, bits, flags);
766         if (ret < 0) {
767                 gnutls_x509_privkey_deinit(pkey->key.x509);
768                 pkey->key.x509 = NULL;
769                 return gnutls_assert_val(ret);
770         }
771
772         pkey->type = GNUTLS_PRIVKEY_X509;
773         pkey->pk_algorithm = algo;
774         pkey->flags = flags | GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE;
775
776         return 0;
777 }
778
779 #ifdef ENABLE_OPENPGP
780 /**
781  * gnutls_privkey_import_openpgp:
782  * @pkey: The private key
783  * @key: The private key to be imported
784  * @flags: Flags for the import
785  *
786  * This function will import the given private key to the abstract
787  * #gnutls_privkey_t type.
788  *
789  * The #gnutls_openpgp_privkey_t object must not be deallocated
790  * during the lifetime of this structure. The subkey set as
791  * preferred will be used, or the master key otherwise.
792  *
793  * @flags might be zero or one of %GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE
794  * and %GNUTLS_PRIVKEY_IMPORT_COPY.
795  *
796  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
797  *   negative error value.
798  *
799  * Since: 2.12.0
800  **/
801 int
802 gnutls_privkey_import_openpgp(gnutls_privkey_t pkey,
803                               gnutls_openpgp_privkey_t key, unsigned int flags)
804 {
805         int ret, idx;
806         uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
807
808         ret = check_if_clean(pkey);
809         if (ret < 0) {
810                 gnutls_assert();
811                 return ret;
812         }
813
814         if (flags & GNUTLS_PRIVKEY_IMPORT_COPY) {
815                 ret = gnutls_openpgp_privkey_init(&pkey->key.openpgp);
816                 if (ret < 0)
817                         return gnutls_assert_val(ret);
818
819                 ret = _gnutls_openpgp_privkey_cpy(pkey->key.openpgp, key);
820                 if (ret < 0) {
821                         gnutls_openpgp_privkey_deinit(pkey->key.openpgp);
822                         return gnutls_assert_val(ret);
823                 }
824         } else
825                 pkey->key.openpgp = key;
826
827         pkey->type = GNUTLS_PRIVKEY_OPENPGP;
828
829         ret = gnutls_openpgp_privkey_get_preferred_key_id(key, keyid);
830         if (ret == GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR) {
831                 pkey->pk_algorithm =
832                     gnutls_openpgp_privkey_get_pk_algorithm(key, NULL);
833         } else {
834                 if (ret < 0)
835                         return gnutls_assert_val(ret);
836
837                 idx = gnutls_openpgp_privkey_get_subkey_idx(key, keyid);
838
839                 pkey->pk_algorithm =
840                     gnutls_openpgp_privkey_get_subkey_pk_algorithm(key,
841                                                                    idx, NULL);
842         }
843
844         pkey->flags = flags;
845
846         return 0;
847 }
848
849 /**
850  * gnutls_privkey_import_openpgp_raw:
851  * @pkey: The private key
852  * @data: The private key data to be imported
853  * @format: The format of the private key
854  * @keyid: The key id to use (optional)
855  * @password: A password (optional)
856  *
857  * This function will import the given private key to the abstract
858  * #gnutls_privkey_t type. 
859  *
860  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
861  *   negative error value.
862  *
863  * Since: 3.1.0
864  **/
865 int gnutls_privkey_import_openpgp_raw(gnutls_privkey_t pkey,
866                                       const gnutls_datum_t * data,
867                                       gnutls_openpgp_crt_fmt_t format,
868                                       const gnutls_openpgp_keyid_t keyid,
869                                       const char *password)
870 {
871         gnutls_openpgp_privkey_t xpriv;
872         int ret;
873
874         ret = gnutls_openpgp_privkey_init(&xpriv);
875         if (ret < 0)
876                 return gnutls_assert_val(ret);
877
878         ret = gnutls_openpgp_privkey_import(xpriv, data, format, password, 0);
879         if (ret < 0) {
880                 gnutls_assert();
881                 goto cleanup;
882         }
883
884         if (keyid) {
885                 ret = gnutls_openpgp_privkey_set_preferred_key_id(xpriv, keyid);
886                 if (ret < 0) {
887                         gnutls_assert();
888                         goto cleanup;
889                 }
890         }
891
892         ret =
893             gnutls_privkey_import_openpgp(pkey, xpriv,
894                                           GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
895         if (ret < 0) {
896                 gnutls_assert();
897                 goto cleanup;
898         }
899
900         return 0;
901
902  cleanup:
903         gnutls_openpgp_privkey_deinit(xpriv);
904
905         return ret;
906 }
907
908 /**
909  * gnutls_privkey_export_openpgp:
910  * @pkey: The private key
911  * @key: Location for the key to be exported.
912  *
913  * Converts the given abstract private key to a #gnutls_openpgp_privkey_t
914  * type. The key must be of type %GNUTLS_PRIVKEY_OPENPGP. The key
915  * returned in @key must be deinitialized with
916  * gnutls_openpgp_privkey_deinit().
917  *
918  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
919  *   negative error value.
920  *
921  * Since: 3.4.0
922  */
923 int
924 gnutls_privkey_export_openpgp(gnutls_privkey_t pkey,
925                               gnutls_openpgp_privkey_t *key)
926 {
927         int ret;
928
929         if (pkey->type != GNUTLS_PRIVKEY_OPENPGP) {
930                 gnutls_assert();
931                 return GNUTLS_E_INVALID_REQUEST;
932         }
933
934         ret = gnutls_openpgp_privkey_init(key);
935         if (ret < 0)
936                 return gnutls_assert_val(ret);
937
938         ret = _gnutls_openpgp_privkey_cpy(*key, pkey->key.openpgp);
939         if (ret < 0) {
940                 gnutls_openpgp_privkey_deinit(*key);
941                 *key = NULL;
942
943                 return gnutls_assert_val(ret);
944         }
945
946         return 0;
947 }
948 #endif
949
950 /**
951  * gnutls_privkey_sign_data:
952  * @signer: Holds the key
953  * @hash: should be a digest algorithm
954  * @flags: Zero or one of %gnutls_privkey_flags_t
955  * @data: holds the data to be signed
956  * @signature: will contain the signature allocated with gnutls_malloc()
957  *
958  * This function will sign the given data using a signature algorithm
959  * supported by the private key. Signature algorithms are always used
960  * together with a hash functions.  Different hash functions may be
961  * used for the RSA algorithm, but only the SHA family for the DSA keys.
962  *
963  * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
964  * the hash algorithm.
965  *
966  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
967  * negative error value.
968  *
969  * Since: 2.12.0
970  **/
971 int
972 gnutls_privkey_sign_data(gnutls_privkey_t signer,
973                          gnutls_digest_algorithm_t hash,
974                          unsigned int flags,
975                          const gnutls_datum_t * data,
976                          gnutls_datum_t * signature)
977 {
978         int ret;
979         gnutls_datum_t digest;
980         const mac_entry_st *me = hash_to_entry(hash);
981
982         if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
983                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
984
985         ret = pk_hash_data(signer->pk_algorithm, me, NULL, data, &digest);
986         if (ret < 0) {
987                 gnutls_assert();
988                 return ret;
989         }
990
991         ret = pk_prepare_hash(signer->pk_algorithm, me, &digest);
992         if (ret < 0) {
993                 gnutls_assert();
994                 goto cleanup;
995         }
996
997         ret = _gnutls_privkey_sign_raw_data(signer, flags, &digest, signature);
998         _gnutls_free_datum(&digest);
999
1000         if (ret < 0) {
1001                 gnutls_assert();
1002                 return ret;
1003         }
1004
1005         return 0;
1006
1007  cleanup:
1008         _gnutls_free_datum(&digest);
1009         return ret;
1010 }
1011
1012 /**
1013  * gnutls_privkey_sign_hash:
1014  * @signer: Holds the signer's key
1015  * @hash_algo: The hash algorithm used
1016  * @flags: Zero or one of %gnutls_privkey_flags_t
1017  * @hash_data: holds the data to be signed
1018  * @signature: will contain newly allocated signature
1019  *
1020  * This function will sign the given hashed data using a signature algorithm
1021  * supported by the private key. Signature algorithms are always used
1022  * together with a hash functions.  Different hash functions may be
1023  * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
1024  *
1025  * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
1026  * the hash algorithm.
1027  *
1028  * Note that if %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA flag is specified this function
1029  * will ignore @hash_algo and perform a raw PKCS1 signature.
1030  *
1031  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1032  *   negative error value.
1033  *
1034  * Since: 2.12.0
1035  **/
1036 int
1037 gnutls_privkey_sign_hash(gnutls_privkey_t signer,
1038                          gnutls_digest_algorithm_t hash_algo,
1039                          unsigned int flags,
1040                          const gnutls_datum_t * hash_data,
1041                          gnutls_datum_t * signature)
1042 {
1043         int ret;
1044         gnutls_datum_t digest;
1045
1046         if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
1047                 return _gnutls_privkey_sign_raw_data(signer, flags,
1048                                                     hash_data, signature);
1049
1050         digest.data = gnutls_malloc(hash_data->size);
1051         if (digest.data == NULL) {
1052                 gnutls_assert();
1053                 return GNUTLS_E_MEMORY_ERROR;
1054         }
1055         digest.size = hash_data->size;
1056         memcpy(digest.data, hash_data->data, digest.size);
1057
1058         ret =
1059             pk_prepare_hash(signer->pk_algorithm, hash_to_entry(hash_algo),
1060                             &digest);
1061         if (ret < 0) {
1062                 gnutls_assert();
1063                 goto cleanup;
1064         }
1065
1066         ret = _gnutls_privkey_sign_raw_data(signer, flags, &digest, signature);
1067         if (ret < 0) {
1068                 gnutls_assert();
1069                 goto cleanup;
1070         }
1071
1072         ret = 0;
1073
1074  cleanup:
1075         _gnutls_free_datum(&digest);
1076         return ret;
1077 }
1078
1079 /*-
1080  * gnutls_privkey_sign_raw_data:
1081  * @key: Holds the key
1082  * @flags: should be zero
1083  * @data: holds the data to be signed
1084  * @signature: will contain the signature allocated with gnutls_malloc()
1085  *
1086  * This function will sign the given data using a signature algorithm
1087  * supported by the private key. Note that this is a low-level function
1088  * and does not apply any preprocessing or hash on the signed data. 
1089  * For example on an RSA key the input @data should be of the DigestInfo
1090  * PKCS #1 1.5 format. Use it only if you know what are you doing.
1091  *
1092  * Note this function is equivalent to using the %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA
1093  * flag with gnutls_privkey_sign_hash().
1094  *
1095  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1096  * negative error value.
1097  *
1098  * Since: 3.1.10
1099  -*/
1100 static int
1101 _gnutls_privkey_sign_raw_data(gnutls_privkey_t key,
1102                              unsigned flags,
1103                              const gnutls_datum_t * data,
1104                              gnutls_datum_t * signature)
1105 {
1106         switch (key->type) {
1107 #ifdef ENABLE_OPENPGP
1108         case GNUTLS_PRIVKEY_OPENPGP:
1109                 return gnutls_openpgp_privkey_sign_hash(key->key.openpgp,
1110                                                         data, signature);
1111 #endif
1112 #ifdef ENABLE_PKCS11
1113         case GNUTLS_PRIVKEY_PKCS11:
1114                 return _gnutls_pkcs11_privkey_sign_hash(key->key.pkcs11,
1115                                                         data, signature);
1116 #endif
1117         case GNUTLS_PRIVKEY_X509:
1118                 return _gnutls_pk_sign(key->key.x509->pk_algorithm,
1119                                        signature, data, &key->key.x509->params);
1120         case GNUTLS_PRIVKEY_EXT:
1121                 if (key->key.ext.sign_func == NULL)
1122                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1123                 return key->key.ext.sign_func(key, key->key.ext.userdata,
1124                                               data, signature);
1125         default:
1126                 gnutls_assert();
1127                 return GNUTLS_E_INVALID_REQUEST;
1128         }
1129 }
1130
1131 /**
1132  * gnutls_privkey_decrypt_data:
1133  * @key: Holds the key
1134  * @flags: zero for now
1135  * @ciphertext: holds the data to be decrypted
1136  * @plaintext: will contain the decrypted data, allocated with gnutls_malloc()
1137  *
1138  * This function will decrypt the given data using the algorithm
1139  * supported by the private key.
1140  *
1141  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1142  * negative error value.
1143  *
1144  * Since: 2.12.0
1145  **/
1146 int
1147 gnutls_privkey_decrypt_data(gnutls_privkey_t key,
1148                             unsigned int flags,
1149                             const gnutls_datum_t * ciphertext,
1150                             gnutls_datum_t * plaintext)
1151 {
1152         switch (key->type) {
1153 #ifdef ENABLE_OPENPGP
1154         case GNUTLS_PRIVKEY_OPENPGP:
1155                 return _gnutls_openpgp_privkey_decrypt_data(key->key.openpgp,
1156                                                             flags, ciphertext,
1157                                                             plaintext);
1158 #endif
1159         case GNUTLS_PRIVKEY_X509:
1160                 return _gnutls_pk_decrypt(key->pk_algorithm, plaintext,
1161                                           ciphertext, &key->key.x509->params);
1162 #ifdef ENABLE_PKCS11
1163         case GNUTLS_PRIVKEY_PKCS11:
1164                 return _gnutls_pkcs11_privkey_decrypt_data(key->key.pkcs11,
1165                                                            flags,
1166                                                            ciphertext,
1167                                                            plaintext);
1168 #endif
1169         case GNUTLS_PRIVKEY_EXT:
1170                 if (key->key.ext.decrypt_func == NULL)
1171                         return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1172
1173                 return key->key.ext.decrypt_func(key,
1174                                                  key->key.ext.userdata,
1175                                                  ciphertext, plaintext);
1176         default:
1177                 gnutls_assert();
1178                 return GNUTLS_E_INVALID_REQUEST;
1179         }
1180 }
1181
1182 /**
1183  * gnutls_privkey_import_x509_raw:
1184  * @pkey: The private key
1185  * @data: The private key data to be imported
1186  * @format: The format of the private key
1187  * @password: A password (optional)
1188  * @flags: an ORed sequence of gnutls_pkcs_encrypt_flags_t
1189  *
1190  * This function will import the given private key to the abstract
1191  * #gnutls_privkey_t type. 
1192  *
1193  * The supported formats are basic unencrypted key, PKCS8, PKCS12, 
1194  * and the openssl format.
1195  *
1196  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1197  *   negative error value.
1198  *
1199  * Since: 3.1.0
1200  **/
1201 int gnutls_privkey_import_x509_raw(gnutls_privkey_t pkey,
1202                                    const gnutls_datum_t * data,
1203                                    gnutls_x509_crt_fmt_t format,
1204                                    const char *password, unsigned int flags)
1205 {
1206         gnutls_x509_privkey_t xpriv;
1207         int ret;
1208
1209         ret = gnutls_x509_privkey_init(&xpriv);
1210         if (ret < 0)
1211                 return gnutls_assert_val(ret);
1212
1213         if (pkey->pin.cb) {
1214                 gnutls_x509_privkey_set_pin_function(xpriv, pkey->pin.cb,
1215                                                      pkey->pin.data);
1216         }
1217
1218         ret = gnutls_x509_privkey_import2(xpriv, data, format, password, flags);
1219         if (ret < 0) {
1220                 gnutls_assert();
1221                 goto cleanup;
1222         }
1223
1224         ret =
1225             gnutls_privkey_import_x509(pkey, xpriv,
1226                                        GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
1227         if (ret < 0) {
1228                 gnutls_assert();
1229                 goto cleanup;
1230         }
1231
1232         return 0;
1233
1234  cleanup:
1235         gnutls_x509_privkey_deinit(xpriv);
1236
1237         return ret;
1238 }
1239
1240 /**
1241  * gnutls_privkey_import_url:
1242  * @key: A key of type #gnutls_privkey_t
1243  * @url: A PKCS 11 url
1244  * @flags: should be zero
1245  *
1246  * This function will import a PKCS11 or TPM URL as a
1247  * private key. The supported URL types can be checked
1248  * using gnutls_url_is_supported().
1249  *
1250  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1251  *   negative error value.
1252  *
1253  * Since: 3.1.0
1254  **/
1255 int
1256 gnutls_privkey_import_url(gnutls_privkey_t key, const char *url,
1257                           unsigned int flags)
1258 {
1259         unsigned i;
1260         int ret;
1261
1262         if (strncmp(url, PKCS11_URL, PKCS11_URL_SIZE) == 0) {
1263 #ifdef ENABLE_PKCS11
1264                 ret = _gnutls_privkey_import_pkcs11_url(key, url, flags);
1265 #else
1266                 ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1267 #endif
1268                 goto cleanup;
1269         }
1270
1271         if (strncmp(url, TPMKEY_URL, TPMKEY_URL_SIZE) == 0) {
1272 #ifdef HAVE_TROUSERS
1273                 ret = gnutls_privkey_import_tpm_url(key, url, NULL, NULL, 0);
1274 #else
1275                 ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
1276 #endif
1277                 goto cleanup;
1278         }
1279
1280         if (strncmp(url, SYSTEM_URL, SYSTEM_URL_SIZE) == 0) {
1281                 ret = _gnutls_privkey_import_system_url(key, url);
1282                 goto cleanup;
1283         }
1284
1285         for (i=0;i<_gnutls_custom_urls_size;i++) {
1286                 if (strncmp(url, _gnutls_custom_urls[i].name, _gnutls_custom_urls[i].name_size) == 0) {
1287                         if (_gnutls_custom_urls[i].import_key) {
1288                                 ret = _gnutls_custom_urls[i].import_key(key, url, flags);
1289                                 goto cleanup;
1290                         }
1291                         break;
1292                 }
1293         }
1294
1295         ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1296  cleanup:
1297         return ret;
1298 }
1299
1300 /**
1301  * gnutls_privkey_set_pin_function:
1302  * @key: A key of type #gnutls_privkey_t
1303  * @fn: the callback
1304  * @userdata: data associated with the callback
1305  *
1306  * This function will set a callback function to be used when
1307  * required to access the object. This function overrides any other
1308  * global PIN functions.
1309  *
1310  * Note that this function must be called right after initialization
1311  * to have effect.
1312  *
1313  * Since: 3.1.0
1314  *
1315  **/
1316 void gnutls_privkey_set_pin_function(gnutls_privkey_t key,
1317                                      gnutls_pin_callback_t fn, void *userdata)
1318 {
1319         key->pin.cb = fn;
1320         key->pin.data = userdata;
1321 }
1322
1323 /**
1324  * gnutls_privkey_status:
1325  * @key: Holds the key
1326  *
1327  * Checks the status of the private key token. This function
1328  * is an actual wrapper over gnutls_pkcs11_privkey_status(), and
1329  * if the private key is a PKCS #11 token it will check whether
1330  * it is inserted or not.
1331  *
1332  * Returns: this function will return non-zero if the token 
1333  * holding the private key is still available (inserted), and zero otherwise.
1334  * 
1335  * Since: 3.1.10
1336  *
1337  **/
1338 int gnutls_privkey_status(gnutls_privkey_t key)
1339 {
1340         switch (key->type) {
1341 #ifdef ENABLE_PKCS11
1342         case GNUTLS_PRIVKEY_PKCS11:
1343                 return gnutls_pkcs11_privkey_status(key->key.pkcs11);
1344 #endif
1345         default:
1346                 return 1;
1347         }
1348 }
1349
1350 /**
1351  * gnutls_privkey_verify_params:
1352  * @key: should contain a #gnutls_privkey_t type
1353  *
1354  * This function will verify the private key parameters.
1355  *
1356  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1357  *   negative error value.
1358  *
1359  * Since: 3.3.0
1360  **/
1361 int gnutls_privkey_verify_params(gnutls_privkey_t key)
1362 {
1363         gnutls_pk_params_st params;
1364         int ret;
1365
1366         gnutls_pk_params_init(&params);
1367
1368         ret = _gnutls_privkey_get_mpis(key, &params);
1369         if (ret < 0)
1370                 return gnutls_assert_val(ret);
1371
1372         ret = _gnutls_pk_verify_priv_params(key->pk_algorithm, &params);
1373
1374         gnutls_pk_params_release(&params);
1375
1376         if (ret < 0) {
1377                 gnutls_assert();
1378                 return ret;
1379         }
1380
1381         return 0;
1382 }
1383
1384 /*-
1385  * _gnutls_privkey_get_preferred_sign_algo:
1386  * @key: should contain a #gnutls_privkey_t type
1387  *
1388  * This function returns the preferred signature algorithm for this
1389  * private key.
1390  *
1391  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
1392  *   negative error value.
1393  *
1394  * Since: 3.4.0
1395  -*/
1396 gnutls_sign_algorithm_t
1397 _gnutls_privkey_get_preferred_sign_algo(gnutls_privkey_t key)
1398 {
1399         if (key->type == GNUTLS_PRIVKEY_EXT) {
1400                 if (key->key.ext.info_func)
1401                         return key->key.ext.info_func(key, GNUTLS_PRIVKEY_INFO_SIGN_ALGO, key->key.ext.userdata);
1402         }
1403         return key->preferred_sign_algo;
1404 }