summaryrefslogtreecommitdiff
path: root/lib/crypto-backend.h
blob: 9874033221d1ee3f52461d5e9f2e7e3083c7c5e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
/*
 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
 *
 * Author: Nikos Mavrogiannopoulos
 *
 * This file is part of GnuTLS.
 *
 * The GnuTLS is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
 *
 */

#ifndef GNUTLS_LIB_CRYPTO_BACKEND_H
#define GNUTLS_LIB_CRYPTO_BACKEND_H

#include <gnutls/crypto.h>

#define gnutls_crypto_single_cipher_st gnutls_crypto_cipher_st
#define gnutls_crypto_single_mac_st gnutls_crypto_mac_st
#define gnutls_crypto_single_digest_st gnutls_crypto_digest_st

typedef struct {
	gnutls_cipher_init_func init;
	gnutls_cipher_setkey_func setkey;
	gnutls_cipher_setiv_func setiv;
	gnutls_cipher_getiv_func getiv;
	gnutls_cipher_encrypt_func encrypt;
	gnutls_cipher_decrypt_func decrypt;
	gnutls_cipher_aead_encrypt_func aead_encrypt;
	gnutls_cipher_aead_decrypt_func aead_decrypt;
	gnutls_cipher_deinit_func deinit;
	gnutls_cipher_auth_func auth;
	gnutls_cipher_tag_func tag;

	/* Not needed for registered on run-time. Only included
	 * should define it. */
	int (*exists) (gnutls_cipher_algorithm_t);	/* true/false */
} gnutls_crypto_cipher_st;

typedef struct {
	gnutls_mac_init_func init;
	gnutls_mac_setkey_func setkey;
	gnutls_mac_setnonce_func setnonce;
	gnutls_mac_hash_func hash;
	gnutls_mac_output_func output;
	gnutls_mac_deinit_func deinit;
	gnutls_mac_fast_func fast;
	gnutls_mac_copy_func copy;

	/* Not needed for registered on run-time. Only included
	 * should define it. */
	int (*exists) (gnutls_mac_algorithm_t);
} gnutls_crypto_mac_st;

typedef struct {
	gnutls_digest_init_func init;
	gnutls_digest_hash_func hash;
	gnutls_digest_output_func output;
	gnutls_digest_deinit_func deinit;
	gnutls_digest_fast_func fast;
	gnutls_digest_copy_func copy;

	/* Not needed for registered on run-time. Only included
	 * should define it. */
	int (*exists) (gnutls_digest_algorithm_t);
} gnutls_crypto_digest_st;

typedef struct {
	int (*hkdf_extract) (gnutls_mac_algorithm_t,
			     const void *key, size_t keysize,
			     const void *salt, size_t saltsize,
			     void *output);
	int (*hkdf_expand) (gnutls_mac_algorithm_t,
			    const void *key, size_t keysize,
			    const void *info, size_t infosize,
			    void *output, size_t length);
	int (*pbkdf2) (gnutls_mac_algorithm_t,
		       const void *key, size_t keysize,
		       const void *salt, size_t saltsize,
		       unsigned iter_count,
		       void *output, size_t length);
} gnutls_crypto_kdf_st;

typedef struct gnutls_crypto_rnd {
	int (*init) (void **ctx); /* called prior to first usage of randomness */
	int (*rnd) (void *ctx, int level, void *data, size_t datasize);
	void (*rnd_refresh) (void *ctx);
	void (*deinit) (void *ctx);
	int (*self_test) (void); /* this should not require rng initialization */
} gnutls_crypto_rnd_st;

typedef void *bigint_t;

/**
 * gnutls_bigint_format_t:
 * @GNUTLS_MPI_FORMAT_USG: Raw unsigned integer format.
 * @GNUTLS_MPI_FORMAT_STD: Raw signed integer format, always a leading
 *   zero when positive.
 *
 * Enumeration of different bignum integer encoding formats.
 */
typedef enum {
	/* raw unsigned integer format */
	GNUTLS_MPI_FORMAT_USG = 0,
	/* raw signed integer format - always a leading zero when positive */
	GNUTLS_MPI_FORMAT_STD = 1,
	/* raw unsigned integer format, little endian format */
	GNUTLS_MPI_FORMAT_ULE = 2
} gnutls_bigint_format_t;

/* Multi precision integer arithmetic */
typedef struct gnutls_crypto_bigint {
	int (*bigint_init) (bigint_t*);
	int (*bigint_init_multi) (bigint_t*, ...);
	void (*bigint_release) (bigint_t n);
	void (*bigint_clear) (bigint_t n);	/* zeros the int */
	/* 0 for equality, > 0 for m1>m2, < 0 for m1<m2 */
	int (*bigint_cmp) (const bigint_t m1, const bigint_t m2);
	/* as bigint_cmp */
	int (*bigint_cmp_ui) (const bigint_t m1, unsigned long m2);
	/* r = a % b */
	int (*bigint_modm) (bigint_t r, const bigint_t a, const bigint_t b);
	/* a = b -> ret == a */
	int (*bigint_set) (bigint_t a, const bigint_t b);
	bigint_t (*bigint_copy) (const bigint_t a);
	/* a = b -> ret == a */
	int (*bigint_set_ui) (bigint_t a, unsigned long b);
	unsigned int (*bigint_get_nbits) (const bigint_t a);
	/* w = b ^ e mod m */
	int (*bigint_powm) (bigint_t w, const bigint_t b,
				 const bigint_t e, const bigint_t m);
	/* w = a + b mod m */
	int (*bigint_addm) (bigint_t w, const bigint_t a,
				 const bigint_t b, const bigint_t m);
	/* w = a - b mod m */
	int (*bigint_subm) (bigint_t w, const bigint_t a,
				 const bigint_t b, const bigint_t m);
	/* w = a * b mod m */
	int (*bigint_mulm) (bigint_t w, const bigint_t a,
				 const bigint_t b, const bigint_t m);
	/* w = a + b */ int (*bigint_add) (bigint_t w,
					       const bigint_t a,
					       const bigint_t b);
	/* w = a - b */ int (*bigint_sub) (bigint_t w,
					       const bigint_t a,
					       const bigint_t b);
	/* w = a * b */
	int (*bigint_mul) (bigint_t w, const bigint_t a,
				const bigint_t b);
	/* w = a + b */
	int (*bigint_add_ui) (bigint_t w, const bigint_t a,
				   unsigned long b);
	/* w = a - b */
	int (*bigint_sub_ui) (bigint_t w, const bigint_t a,
				   unsigned long b);
	/* w = a * b */
	int (*bigint_mul_ui) (bigint_t w, const bigint_t a,
				   unsigned long b);
	/* q = a / b */
	int (*bigint_div) (bigint_t q, const bigint_t a,
				const bigint_t b);
	/* 0 if prime */
	int (*bigint_prime_check) (const bigint_t pp);

	/* reads a bigint from a buffer */
	/* stores a bigint into the buffer.  returns
	 * GNUTLS_E_SHORT_MEMORY_BUFFER if buf_size is not sufficient to
	 * store this integer, and updates the buf_size;
	 */
	int (*bigint_scan) (bigint_t m, const void *buf, size_t buf_size,
				 gnutls_bigint_format_t format);
	int (*bigint_print) (const bigint_t a, void *buf,
			     size_t * buf_size,
			     gnutls_bigint_format_t format);
} gnutls_crypto_bigint_st;

/* Additional information about the public key, filled from
 * SubjectPublicKeyInfo parameters. When there are no parameters,
 * the pk field will be set to GNUTLS_PK_UNKNOWN.
 */
typedef struct gnutls_x509_spki_st {
	/* We can have a key which is of type RSA, but a certificate
	 * of type RSA-PSS; the value here will be the expected value
	 * for signatures (i.e., RSA-PSS) */
	gnutls_pk_algorithm_t pk;

	/* the digest used by RSA-PSS */
	gnutls_digest_algorithm_t rsa_pss_dig;

	/* the size of salt used by RSA-PSS */
	unsigned int salt_size;

	/* if non-zero, the legacy value for PKCS#7 signatures will be
	 * written for RSA signatures. */
	unsigned int legacy;

	/* the digest used by ECDSA/DSA */
	gnutls_digest_algorithm_t dsa_dig;

	/* flags may include GNUTLS_PK_FLAG_REPRODUCIBLE for
	 * deterministic ECDSA/DSA */
	unsigned int flags;
} gnutls_x509_spki_st;

#define GNUTLS_MAX_PK_PARAMS 16

typedef struct {
	bigint_t params[GNUTLS_MAX_PK_PARAMS];
	unsigned int params_nr;	/* the number of parameters */
	unsigned int pkflags; /* gnutls_pk_flag_t */
	unsigned int qbits; /* GNUTLS_PK_DH */
	gnutls_ecc_curve_t curve; /* GNUTLS_PK_EC, GNUTLS_PK_ED25519, GNUTLS_PK_GOST* */
	gnutls_group_t dh_group; /* GNUTLS_PK_DH - used by ext/key_share */
	gnutls_gost_paramset_t gost_params; /* GNUTLS_PK_GOST_* */
	gnutls_datum_t raw_pub; /* used by x25519 */
	gnutls_datum_t raw_priv;

	unsigned int seed_size;
	uint8_t seed[MAX_PVP_SEED_SIZE];
	gnutls_digest_algorithm_t palgo;
	/* public key information */
	gnutls_x509_spki_st spki;

	gnutls_pk_algorithm_t algo;
} gnutls_pk_params_st;

/**
 * gnutls_pk_flag_t:
 * @GNUTLS_PK_FLAG_NONE: No flag.
 *
 * Enumeration of public-key flag.
 */
typedef enum {
	GNUTLS_PK_FLAG_NONE = 0,
	GNUTLS_PK_FLAG_PROVABLE = 1,
	GNUTLS_PK_FLAG_REPRODUCIBLE = 2,
	GNUTLS_PK_FLAG_RSA_PSS_FIXED_SALT_LENGTH = 4
} gnutls_pk_flag_t;

#define FIX_SIGN_PARAMS(params, flags, dig) do {		\
	if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) {	\
		(params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE;	\
		(params).dsa_dig = (dig);			\
	}							\
} while (0)

void gnutls_pk_params_release(gnutls_pk_params_st * p);
void gnutls_pk_params_clear(gnutls_pk_params_st * p);
void gnutls_pk_params_init(gnutls_pk_params_st * p);


#define MAX_PUBLIC_PARAMS_SIZE 4	/* ok for RSA and DSA */

/* parameters should not be larger than this limit */
#define DSA_PUBLIC_PARAMS 4
#define DH_PUBLIC_PARAMS 4
#define RSA_PUBLIC_PARAMS 2
#define ECC_PUBLIC_PARAMS 2
#define GOST_PUBLIC_PARAMS 2


#define MAX_PRIV_PARAMS_SIZE GNUTLS_MAX_PK_PARAMS	/* ok for RSA and DSA */

/* parameters should not be larger than this limit */
#define DSA_PRIVATE_PARAMS 5
#define DH_PRIVATE_PARAMS 5
#define RSA_PRIVATE_PARAMS 8
#define ECC_PRIVATE_PARAMS 3
#define GOST_PRIVATE_PARAMS 3

#if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0
#error INCREASE MAX_PRIV_PARAMS
#endif

#if MAX_PRIV_PARAMS_SIZE - ECC_PRIVATE_PARAMS < 0
#error INCREASE MAX_PRIV_PARAMS
#endif

#if MAX_PRIV_PARAMS_SIZE - GOST_PRIVATE_PARAMS < 0
#error INCREASE MAX_PRIV_PARAMS
#endif

#if MAX_PRIV_PARAMS_SIZE - DSA_PRIVATE_PARAMS < 0
#error INCREASE MAX_PRIV_PARAMS
#endif


/* params are:
 * RSA:
 *  [0] is modulus
 *  [1] is public exponent
 *  [2] is private exponent (private key only)
 *  [3] is prime1 (p) (private key only)
 *  [4] is prime2 (q) (private key only)
 *  [5] is coefficient (u == inverse of p mod q) (private key only)
 *  [6] e1 == d mod (p-1)
 *  [7] e2 == d mod (q-1)
 *
 *  note that for libgcrypt that does not use the inverse of q mod p,
 *  we need to perform conversions using fixup_params().
 *
 * DSA:
 *  [0] is p
 *  [1] is q
 *  [2] is g
 *  [3] is y (public key)
 *  [4] is x (private key only)
 *
 * DH: as DSA
 *
 * ECC:
 *  [0] is prime
 *  [1] is order
 *  [2] is A
 *  [3] is B
 *  [4] is Gx
 *  [5] is Gy
 *  [6] is x
 *  [7] is y
 *  [8] is k (private key)
 */

#define ECC_X 0
#define ECC_Y 1
#define ECC_K 2

#define GOST_X 0
#define GOST_Y 1
#define GOST_K 2

#define DSA_P 0
#define DSA_Q 1
#define DSA_G 2
#define DSA_Y 3
#define DSA_X 4

#define DH_P 0
#define DH_Q 1
#define DH_G 2
#define DH_Y 3
#define DH_X 4

#define RSA_MODULUS 0
#define RSA_PUB 1
#define RSA_PRIV 2
#define RSA_PRIME1 3
#define RSA_PRIME2 4
#define RSA_COEF 5
#define RSA_E1 6
#define RSA_E2 7

/**
 * gnutls_direction_t:
 * @GNUTLS_IMPORT: Import direction.
 * @GNUTLS_EXPORT: Export direction.
 *
 * Enumeration of different directions.
 */
typedef enum {
	GNUTLS_IMPORT = 0,
	GNUTLS_EXPORT = 1
} gnutls_direction_t;

/* Public key algorithms */
typedef struct gnutls_crypto_pk {
	/* The params structure should contain the private or public key
	 * parameters, depending on the operation */
	int (*encrypt) (gnutls_pk_algorithm_t, gnutls_datum_t * ciphertext,
			const gnutls_datum_t * plaintext,
			const gnutls_pk_params_st * pub);
	int (*decrypt) (gnutls_pk_algorithm_t,
                        gnutls_datum_t * plaintext,
			const gnutls_datum_t * ciphertext,
			const gnutls_pk_params_st * priv);
	int (*decrypt2) (gnutls_pk_algorithm_t,
			 const gnutls_datum_t * ciphertext,
                         unsigned char * plaintext,
                         size_t paintext_size,
			 const gnutls_pk_params_st * priv);
	int (*sign) (gnutls_pk_algorithm_t, gnutls_datum_t * signature,
		     const gnutls_datum_t * data,
		     const gnutls_pk_params_st *priv,
		     const gnutls_x509_spki_st *sign);
	int (*verify) (gnutls_pk_algorithm_t, const gnutls_datum_t * data,
		       const gnutls_datum_t * sig,
		       const gnutls_pk_params_st *pub,
		       const gnutls_x509_spki_st *sign);
	/* sanity checks the public key parameters */
	int (*verify_priv_params) (gnutls_pk_algorithm_t,
			      const gnutls_pk_params_st * priv);
	int (*verify_pub_params) (gnutls_pk_algorithm_t,
			      const gnutls_pk_params_st * pub);
	int (*generate_keys) (gnutls_pk_algorithm_t, unsigned int nbits,
			 gnutls_pk_params_st *, unsigned ephemeral);
	int (*generate_params) (gnutls_pk_algorithm_t, unsigned int nbits,
			 gnutls_pk_params_st *);
	/* this function should convert params to ones suitable
	 * for the above functions
	 */
	int (*pk_fixup_private_params) (gnutls_pk_algorithm_t,
					gnutls_direction_t,
					gnutls_pk_params_st *);
#define PK_DERIVE_TLS13 1
	int (*derive) (gnutls_pk_algorithm_t, gnutls_datum_t * out,
		       const gnutls_pk_params_st * priv,
		       const gnutls_pk_params_st * pub,
		       const gnutls_datum_t *nonce,
		       unsigned int flags);

	int (*curve_exists) (gnutls_ecc_curve_t);	/* true/false */
} gnutls_crypto_pk_st;

/* priority: infinity for backend algorithms, 90 for kernel
   algorithms, lowest wins
 */
int gnutls_crypto_single_cipher_register(gnutls_cipher_algorithm_t
					 algorithm, int priority,
					 const gnutls_crypto_single_cipher_st *s,
					 int free_s);
int gnutls_crypto_single_mac_register(gnutls_mac_algorithm_t algorithm,
				      int priority,
				      const gnutls_crypto_single_mac_st *
				      s, int free_s);
int gnutls_crypto_single_digest_register(gnutls_digest_algorithm_t
					 algorithm, int priority,
					 const
					 gnutls_crypto_single_digest_st *
					 s, int free_s);

int gnutls_crypto_rnd_register(int priority,
			       const gnutls_crypto_rnd_st * s);
int gnutls_crypto_pk_register(int priority, const gnutls_crypto_pk_st * s);
int gnutls_crypto_bigint_register(int priority,
				  const gnutls_crypto_bigint_st * s);

/* Provided by crypto-backend */
int
_gnutls_prf_raw(gnutls_mac_algorithm_t mac,
		size_t master_size, const void *master,
		size_t label_size, const char *label,
		size_t seed_size, const uint8_t *seed, size_t outsize,
		char *out);

int _gnutls_gost_key_wrap(gnutls_gost_paramset_t gost_params,
			  const gnutls_datum_t *kek,
			  const gnutls_datum_t *ukm,
			  const gnutls_datum_t *cek,
			  gnutls_datum_t *enc,
			  gnutls_datum_t *imit);

int _gnutls_gost_key_unwrap(gnutls_gost_paramset_t gost_params,
			    const gnutls_datum_t *kek,
			    const gnutls_datum_t *ukm,
			    const gnutls_datum_t *enc,
			    const gnutls_datum_t *imit,
			    gnutls_datum_t *cek);

int
_gnutls_rsa_pkcs1_sign_pad(size_t key_bits,
			   const gnutls_datum_t *data,
			   unsigned char *buffer, size_t buffer_size);

int
_gnutls_rsa_pss_sign_pad(gnutls_x509_spki_st *params,
			 size_t key_bits,
			 const gnutls_datum_t *data,
			 unsigned char *buffer, size_t buffer_size);

#endif /* GNUTLS_LIB_CRYPTO_BACKEND_H */