summaryrefslogtreecommitdiff
path: root/chip/g/dcrypto/dcrypto.h
blob: 93763b1f262aa2f52114ef6ca4434b1f3dd23d29 (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
/* Copyright 2015 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/*
 * Crypto wrapper library for the g chip.
 */
#ifndef __EC_CHIP_G_DCRYPTO_DCRYPTO_H
#define __EC_CHIP_G_DCRYPTO_DCRYPTO_H

#if defined(CR50_DEV) && (CR50_DEV) > 1
#define CRYPTO_TEST_SETUP
#endif

#include "internal.h"

#include "crypto_api.h"

#include <stddef.h>

#include "cryptoc/hmac.h"

enum cipher_mode {
	CIPHER_MODE_ECB = 0,
	CIPHER_MODE_CTR = 1,
	CIPHER_MODE_CBC = 2,
	CIPHER_MODE_GCM = 3
};

enum encrypt_mode {
	DECRYPT_MODE = 0,
	ENCRYPT_MODE = 1
};

enum hashing_mode {
	HASH_SHA1 = 0,
	HASH_SHA256 = 1,
	HASH_SHA384 = 2,  /* Only supported for PKCS#1 signing */
	HASH_SHA512 = 3,  /* Only supported for PKCS#1 signing */
	HASH_NULL = 4  /* Only supported for PKCS#1 signing */
};

/*
 * AES implementation, based on a hardware AES block.
 */
#define AES256_BLOCK_CIPHER_KEY_SIZE       32

int DCRYPTO_aes_init(const uint8_t *key, uint32_t key_len, const uint8_t *iv,
		enum cipher_mode c_mode, enum encrypt_mode e_mode);
int DCRYPTO_aes_block(const uint8_t *in, uint8_t *out);

void DCRYPTO_aes_write_iv(const uint8_t *iv);
void DCRYPTO_aes_read_iv(uint8_t *iv);
int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits,
		const uint8_t *iv, const uint8_t *in, size_t in_len);

/* AES-GCM-128 */
struct GCM_CTX {
	union {
		uint32_t d[4];
		uint8_t c[16];
	} block, Ej0;

	uint64_t aad_len;
	uint64_t count;
	size_t remainder;
};

/* Initialize the GCM context structure. */
void DCRYPTO_gcm_init(struct GCM_CTX *ctx, const uint8_t *key,
		const uint8_t *iv, size_t iv_len);
/* Additional authentication data to include in the tag calculation. */
void DCRYPTO_gcm_aad(struct GCM_CTX *ctx, const uint8_t *aad_data, size_t len);
/* Encrypt & decrypt return the number of bytes written to out
 * (always an integral multiple of 16), or -1 on error.  These functions
 * may be called repeatedly with incremental data.
 *
 * NOTE: if in_len is not a integral multiple of 16, then out_len must
 * be atleast in_len - (in_len % 16) + 16 bytes.
 */
int DCRYPTO_gcm_encrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len,
			const uint8_t *in, size_t in_len);
int DCRYPTO_gcm_decrypt(struct GCM_CTX *ctx, uint8_t *out, size_t out_len,
			const uint8_t *in, size_t in_len);
/* Encrypt & decrypt a partial final block, if any.  These functions
 * return the number of bytes written to out (<= 15), or -1 on error.
 */
int DCRYPTO_gcm_encrypt_final(struct GCM_CTX *ctx,
			uint8_t *out, size_t out_len);
int DCRYPTO_gcm_decrypt_final(struct GCM_CTX *ctx,
			uint8_t *out, size_t out_len);
/* Compute the tag over AAD + encrypt or decrypt data, and return the
 * number of bytes written to tag.  Returns -1 on error.
 */
int DCRYPTO_gcm_tag(struct GCM_CTX *ctx, uint8_t *tag, size_t tag_len);
/* Cleanup secrets. */
void DCRYPTO_gcm_finish(struct GCM_CTX *ctx);

/* AES-CMAC-128 */
/* K: 128-bit key, M: message, len: number of bytes in M
 * Writes 128-bit tag to T; returns 0 if an error is encountered and 1
 * otherwise.
 */
int DCRYPTO_aes_cmac(const uint8_t *K, const uint8_t *M, const uint32_t len,
		uint32_t T[4]);
/* key: 128-bit key, M: message, len: number of bytes in M,
 *    T: tag to be verified
 * Returns 1 if the tag is correct and 0 otherwise.
 */
int DCRYPTO_aes_cmac_verify(const uint8_t *key, const uint8_t *M, const int len,
		const uint32_t T[4]);

/*
 * SHA implementation.  This abstraction is backed by either a
 * software or hardware implementation.
 *
 * There could be only a single hardware SHA context in progress. The init
 * functions will try using the HW context, if available, unless 'sw_required'
 * is TRUE, in which case there will be no attempt to use the hardware for
 * this particular hashing session.
 */
void DCRYPTO_SHA1_init(SHA_CTX *ctx, uint32_t sw_required);
void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required);
void DCRYPTO_SHA384_init(LITE_SHA384_CTX *ctx);
void DCRYPTO_SHA512_init(LITE_SHA512_CTX *ctx);
const uint8_t *DCRYPTO_SHA1_hash(const void *data, uint32_t n,
				uint8_t *digest);
const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n,
				   uint8_t *digest);
const uint8_t *DCRYPTO_SHA384_hash(const void *data, uint32_t n,
				   uint8_t *digest);
const uint8_t *DCRYPTO_SHA512_hash(const void *data, uint32_t n,
				   uint8_t *digest);
/*
 *  HMAC.
 */
void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
			unsigned int len);
const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx);

/*
 * BIGNUM utility methods.
 */
void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len);

/*
 *  RSA.
 */

/* Largest supported key size for signing / encryption: 2048-bits.
 * Verification is a special case and supports 4096-bits (signing /
 * decryption could also support 4k-RSA, but is disabled since support
 * is not required, and enabling support would result in increased
 * stack usage for all key sizes.)
 */
#define RSA_BYTES_2K    256
#define RSA_BYTES_4K    512
#define RSA_WORDS_2K    (RSA_BYTES_2K / sizeof(uint32_t))
#define RSA_WORDS_4K    (RSA_BYTES_4K / sizeof(uint32_t))
#ifndef RSA_MAX_BYTES
#define RSA_MAX_BYTES   RSA_BYTES_2K
#endif
#define RSA_MAX_WORDS   (RSA_MAX_BYTES / sizeof(uint32_t))
#define RSA_F4          65537

struct RSA {
	uint32_t e;
	struct LITE_BIGNUM N;
	struct LITE_BIGNUM d;
};

enum padding_mode {
	PADDING_MODE_PKCS1 = 0,
	PADDING_MODE_OAEP  = 1,
	PADDING_MODE_PSS = 2,
	/* USE OF NULL PADDING IS NOT RECOMMENDED.
	 * SUPPORT EXISTS AS A REQUIREMENT FOR TPM2 OPERATION. */
	PADDING_MODE_NULL  = 3
};

/* Calculate r = m ^ e mod N */
int DCRYPTO_rsa_encrypt(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
			const uint8_t *in, uint32_t in_len,
			enum padding_mode padding, enum hashing_mode hashing,
			const char *label);

/* Calculate r = m ^ d mod N */
int DCRYPTO_rsa_decrypt(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
			const uint8_t *in, const uint32_t in_len,
			enum padding_mode padding, enum hashing_mode hashing,
			const char *label);

/* Calculate r = m ^ d mod N */
int DCRYPTO_rsa_sign(struct RSA *rsa, uint8_t *out, uint32_t *out_len,
		const uint8_t *in, const uint32_t in_len,
		enum padding_mode padding, enum hashing_mode hashing);

/* Calculate r = m ^ e mod N */
int DCRYPTO_rsa_verify(const struct RSA *rsa, const uint8_t *digest,
		uint32_t digest_len, const uint8_t *sig,
		const uint32_t sig_len,	enum padding_mode padding,
		enum hashing_mode hashing);

/* Calculate n = p * q, d = e ^ -1 mod phi. */
int DCRYPTO_rsa_key_compute(struct LITE_BIGNUM *N, struct LITE_BIGNUM *d,
			struct LITE_BIGNUM *p, struct LITE_BIGNUM *q,
			uint32_t e);

/*
 *  EC.
 */
int DCRYPTO_p256_base_point_mul(p256_int *out_x, p256_int *out_y,
				const p256_int *n);
int DCRYPTO_p256_point_mul(p256_int *out_x, p256_int *out_y,
			const p256_int *n, const p256_int *in_x,
			const p256_int *in_y);
/*
 * Produce uniform private key from seed.
 * If x or y is NULL, the public key part is not computed.
 * Returns !0 on success.
 */
int DCRYPTO_p256_key_from_bytes(p256_int *x, p256_int *y, p256_int *d,
				const uint8_t bytes[P256_NBYTES]);
/* P256 based integration encryption (DH+AES128+SHA256). */
/* Authenticated data may be provided, where the first auth_data_len
 * bytes of in will be authenticated but not encrypted. */
/* Supports in-place encryption / decryption. */
size_t DCRYPTO_ecies_encrypt(
	void *out, size_t out_len, const void *in, size_t in_len,
	size_t auth_data_len, const uint8_t *iv,
	const p256_int *pub_x, const p256_int *pub_y,
	const uint8_t *salt, size_t salt_len,
	const uint8_t *info, size_t info_len);
size_t DCRYPTO_ecies_decrypt(
	void *out, size_t out_len, const void *in, size_t in_len,
	size_t auth_data_len, const uint8_t *iv,
	const p256_int *d,
	const uint8_t *salt, size_t salt_len,
	const uint8_t *info, size_t info_len);

/*
 *  HKDF.
 */
int DCRYPTO_hkdf(uint8_t *OKM, size_t OKM_len,
		const uint8_t *salt, size_t salt_len,
		const uint8_t *IKM, size_t IKM_len,
		const uint8_t *info, size_t info_len);

/*
 *  BN.
 */
int DCRYPTO_bn_generate_prime(struct LITE_BIGNUM *p);
void DCRYPTO_bn_wrap(struct LITE_BIGNUM *b, void *buf, size_t len);
void DCRYPTO_bn_mul(struct LITE_BIGNUM *c, const struct LITE_BIGNUM *a,
		const struct LITE_BIGNUM *b);
int DCRYPTO_bn_div(struct LITE_BIGNUM *quotient, struct LITE_BIGNUM *remainder,
		const struct LITE_BIGNUM *input,
		const struct LITE_BIGNUM *divisor);

/*
 * ASN.1 DER
 */
size_t DCRYPTO_asn1_sigp(uint8_t *buf, const p256_int *r, const p256_int *s);
size_t DCRYPTO_asn1_pubp(uint8_t *buf, const p256_int *x, const p256_int *y);

/*
 *  X509.
 */
int DCRYPTO_x509_verify(const uint8_t *cert, size_t len,
			const struct RSA *ca_pub_key);
int DCRYPTO_x509_gen_u2f_cert(const p256_int *d, const p256_int *pk_x,
			const p256_int *pk_y, const p256_int *serial,
			uint8_t *cert, const int n);

/*
 * Memory related functions.
 */
int DCRYPTO_equals(const void *a, const void *b, size_t len);

/*
 * Key-ladder and application key related functions.
 */
enum dcrypto_appid {
	RESERVED = 0,
	NVMEM = 1,
	U2F_ATTEST = 2,
	U2F_ORIGIN = 3,
	U2F_WRAP = 4,
	PERSO_AUTH = 5,
	PINWEAVER = 6,
	/* This enum value should not exceed 7. */
};

struct APPKEY_CTX {
#ifdef TEST_FUZZ
	uint8_t unused_for_cxx_compatibility;
#endif
};

int DCRYPTO_ladder_compute_frk2(size_t major_fw_version, uint8_t *frk2);
int DCRYPTO_ladder_random(void *output);

int DCRYPTO_appkey_init(enum dcrypto_appid id, struct APPKEY_CTX *ctx);
void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx);
int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8],
			  uint32_t output[8]);

/* Number of bytes in the salt object. */
#define DCRYPTO_CIPHER_SALT_SIZE 16
BUILD_ASSERT(DCRYPTO_CIPHER_SALT_SIZE == CIPHER_SALT_SIZE);

/*
 * Encrypt/decrypt a flat blob.
 *
 * Encrypt or decrypt the input buffer, and write the correspondingly
 * ciphered output to out.  The number of bytes produced is equal to
 * the number of input bytes.  Note that the input and output pointers
 * MUST be word-aligned.
 *
 * This API is expected to be applied to a single contiguous region.

 * WARNING: A given salt/"in" pair MUST be unique, i.e. re-using a
 * salt with a logically different input buffer is catastrophic.  An
 * example of a suitable salt is one that is derived from "in", e.g. a
 * digest of the input data.
 *
 * @param appid the application-id of the calling context.
 * @param salt pointer to a unique value to be associated with this blob,
 *	       used for derivation of the proper IV, the size of the value
 *	       is as defined by DCRYPTO_CIPHER_SALT_SIZE above.
 * @param out Destination pointer where to write plaintext / ciphertext.
 * @param in  Source pointer where to read ciphertext / plaintext.
 * @param len Number of bytes to read from in / write to out.
 * @return non-zero on success, and zero otherwise.
 */
int DCRYPTO_app_cipher(enum dcrypto_appid appid, const void *salt,
		void *out, const void *in, size_t len);

#endif  /* ! __EC_CHIP_G_DCRYPTO_DCRYPTO_H */