summaryrefslogtreecommitdiff
path: root/board/cr50/dcrypto/internal.h
blob: be217185c734d670f03207424b5c0bd2db416004 (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
/* 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.
 */
#ifndef __EC_CHIP_G_DCRYPTO_INTERNAL_H
#define __EC_CHIP_G_DCRYPTO_INTERNAL_H

#include <stddef.h>
#include <string.h>

#include "common.h"
#include "util.h"

#include "hmacsha2.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * SHA.
 */
#define CTRL_CTR_BIG_ENDIAN (__BYTE_ORDER__  == __ORDER_BIG_ENDIAN__)
#define CTRL_ENABLE         1
#define CTRL_ENCRYPT        1
#define CTRL_NO_SOFT_RESET  0

#define SHA_DIGEST_WORDS   (SHA_DIGEST_SIZE / sizeof(uint32_t))
#define SHA256_DIGEST_WORDS (SHA256_DIGEST_SIZE / sizeof(uint32_t))

#ifdef CONFIG_UPTO_SHA512
#define SHA_DIGEST_MAX_BYTES SHA512_DIGEST_SIZE
#else
#define SHA_DIGEST_MAX_BYTES SHA256_DIGEST_SIZE
#endif

#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif

enum sha_mode {
	SHA1_MODE = 0,
	SHA256_MODE = 1
};

/*
 * Use this structure to avoid alignment problems with input and output
 * pointers.
 */
struct access_helper {
	uint32_t udata;
} __packed;

#ifndef SECTION_IS_RO
int dcrypto_grab_sha_hw(void);
void dcrypto_release_sha_hw(void);
#endif

/*
 * BIGNUM.
 */
#define LITE_BN_BITS2        32
#define LITE_BN_BYTES        4

struct LITE_BIGNUM {
	uint32_t dmax;              /* Size of d, in 32-bit words. */
	struct access_helper *d;  /* Word array, little endian format ... */
};

#define BN_DIGIT(b, i) ((b)->d[(i)].udata)

void bn_init(struct LITE_BIGNUM *bn, void *buf, size_t len);
#define bn_size(b) ((b)->dmax * LITE_BN_BYTES)
#define bn_words(b) ((b)->dmax)
#define bn_bits(b) ((b)->dmax * LITE_BN_BITS2)
int bn_eq(const struct LITE_BIGNUM *a, const struct LITE_BIGNUM *b);
int bn_check_topbit(const struct LITE_BIGNUM *N);
int bn_modexp(struct LITE_BIGNUM *output,
			const struct LITE_BIGNUM *input,
			const struct LITE_BIGNUM *exp,
			const struct LITE_BIGNUM *N);
int bn_modexp_word(struct LITE_BIGNUM *output,
			const struct LITE_BIGNUM *input,
			uint32_t pubexp,
			const struct LITE_BIGNUM *N);
int bn_modexp_blinded(struct LITE_BIGNUM *output,
			const struct LITE_BIGNUM *input,
			const struct LITE_BIGNUM *exp,
			const struct LITE_BIGNUM *N,
			uint32_t pubexp);
uint32_t bn_add(struct LITE_BIGNUM *c,
		const struct LITE_BIGNUM *a);
uint32_t bn_sub(struct LITE_BIGNUM *c,
		const struct LITE_BIGNUM *a);
int bn_modinv_vartime(struct LITE_BIGNUM *r,
			const struct LITE_BIGNUM *e,
			const struct LITE_BIGNUM *MOD);
int bn_is_bit_set(const struct LITE_BIGNUM *a, int n);

/*
 * Accelerated bn.
 */
int dcrypto_modexp(struct LITE_BIGNUM *output,
			const struct LITE_BIGNUM *input,
			const struct LITE_BIGNUM *exp,
			const struct LITE_BIGNUM *N);
int dcrypto_modexp_word(struct LITE_BIGNUM *output,
			const struct LITE_BIGNUM *input,
			uint32_t pubexp,
			const struct LITE_BIGNUM *N);
int dcrypto_modexp_blinded(struct LITE_BIGNUM *output,
			const struct LITE_BIGNUM *input,
			const struct LITE_BIGNUM *exp,
			const struct LITE_BIGNUM *N,
			uint32_t pubexp);

struct drbg_ctx {
	uint32_t k[SHA256_DIGEST_WORDS];
	uint32_t v[SHA256_DIGEST_WORDS];
	uint32_t reseed_counter;
};

/*
 * NIST SP 800-90A HMAC DRBG.
 */
enum hmac_result {
	HMAC_DRBG_SUCCESS = 0,
	HMAC_DRBG_INVALID_PARAM = 1,
	HMAC_DRBG_RESEED_REQUIRED = 2
};

/* Standard initialization. */
void hmac_drbg_init(struct drbg_ctx *ctx,
		    const void *p0, size_t p0_len,
		    const void *p1, size_t p1_len,
		    const void *p2, size_t p2_len);
/* Initialize with at least nbits of random entropy. */
void hmac_drbg_init_rand(struct drbg_ctx *ctx, size_t nbits);
void hmac_drbg_reseed(struct drbg_ctx *ctx,
		      const void *p0, size_t p0_len,
		      const void *p1, size_t p1_len,
		      const void *p2, size_t p2_len);
enum hmac_result hmac_drbg_generate(struct drbg_ctx *ctx, void *out,
				    size_t out_len, const void *input,
				    size_t input_len);
void drbg_exit(struct drbg_ctx *ctx);

/* Set seed for fast random number generator using LFSR. */
void set_fast_random_seed(uint32_t seed);

/* Generate week pseudorandom using LFSR for blinding purposes. */
uint32_t fast_random(void);

/*
 * Accelerated p256. FIPS PUB 186-4
 */
#define P256_BITSPERDIGIT 32
#define P256_NDIGITS	  8
#define P256_NBYTES	  32

typedef uint32_t p256_digit;
typedef int32_t p256_sdigit;
typedef uint64_t p256_ddigit;
typedef int64_t p256_sddigit;

#define P256_DIGITS(x)	 ((x)->a)
#define P256_DIGIT(x, y) ((x)->a[y])

/**
 * P-256 integers internally represented as little-endian 32-bit integer
 * digits in platform-specific format. On little-endian platform this would
 * be regular 256-bit little-endian unsigned integer. On big-endian platform
 * it would big-endian 32-bit digits in little-endian order.
 *
 * Defining p256_int as struct to leverage struct assignment.
 */
typedef struct p256_int {
	union {
		p256_digit a[P256_NDIGITS];
		uint8_t b8[P256_NBYTES];
	};
} __packed p256_int;

extern const p256_int SECP256r1_nMin2;

/* Clear a p256_int to zero. */
void p256_clear(p256_int *a);

/* Check p256 is a zero. */
int p256_is_zero(const p256_int *a);

/* Check p256 is odd. */
int p256_is_odd(const p256_int *a);

/* c := a + (single digit)b, returns carry 1 on carry. */
int p256_add_d(const p256_int *a, p256_digit b, p256_int *c);

/* Returns -1, 0 or 1. */
int p256_cmp(const p256_int *a, const p256_int *b);

/* Return -1 if a < b. */
int p256_lt_blinded(const p256_int *a, const p256_int *b);

/* Outputs big-endian binary form. No leading zero skips. */
void p256_to_bin(const p256_int *src, uint8_t dst[P256_NBYTES]);

/**
 * Reads from big-endian binary form, thus pre-pad with leading
 * zeros if short. Input length is assumed P256_NBYTES bytes.
 */
void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int *dst);

int dcrypto_p256_ecdsa_sign(struct drbg_ctx *drbg, const p256_int *key,
			    const p256_int *message, p256_int *r, p256_int *s)
	__attribute__((warn_unused_result));
int dcrypto_p256_base_point_mul(const p256_int *k, p256_int *x, p256_int *y)
	__attribute__((warn_unused_result));
int dcrypto_p256_point_mul(const p256_int *k,
		const p256_int *in_x, const p256_int *in_y,
		p256_int *x, p256_int *y)
	__attribute__((warn_unused_result));
int dcrypto_p256_ecdsa_verify(const p256_int *key_x, const p256_int *key_y,
		const p256_int *message, const p256_int *r,
		const p256_int *s)
	__attribute__((warn_unused_result));
int dcrypto_p256_is_valid_point(const p256_int *x, const p256_int *y)
	__attribute__((warn_unused_result));

/* Wipe content of rnd with pseudo-random values. */
void p256_fast_random(p256_int *rnd);

/* Generate a p256 number between 1 < k < |p256| using provided DRBG. */
enum hmac_result p256_hmac_drbg_generate(struct drbg_ctx *ctx, p256_int *k_out);

/* Initialize for use as RFC6979 DRBG. */
void hmac_drbg_init_rfc6979(struct drbg_ctx *ctx,
			    const p256_int *key,
			    const p256_int *message);

/*
 * Accelerator runtime.
 *
 * Note dcrypto_init_and_lock grabs a mutex and dcrypto_unlock releases it.
 * Do not use dcrypto_call, dcrypto_imem_load or dcrypto_dmem_load w/o holding
 * the mutex.
 */
void dcrypto_init_and_lock(void);
void dcrypto_unlock(void);
uint32_t dcrypto_call(uint32_t adr) __attribute__((warn_unused_result));
void dcrypto_imem_load(size_t offset, const uint32_t *opcodes,
		       size_t n_opcodes);
/*
 * Returns 0 iff no difference was observed between existing and new content.
 */
uint32_t dcrypto_dmem_load(size_t offset, const void *words, size_t n_words);

/**
 * An implementation of memset that ought not to be optimized away;
 * useful for scrubbing security sensitive buffers.
 */
void *always_memset(void *s, int c, size_t n);

#ifndef __alias
#define __alias(func) __attribute__((alias(#func)))
#endif

/* rotate 32-bit value right */
static inline uint32_t ror(uint32_t value, int bits)
{
	/* return __builtin_rotateright32(value, bits); */
	return (value >> bits) | (value << (32 - bits));
}

/* rotate 64-bit value right */
static inline uint64_t ror64(uint64_t value, int bits)
{
	/* return __builtin_rotateright64(value, bits); */
	return (value >> bits) | (value << (64 - bits));
}

/* rotate 32-bit value left */
static inline uint32_t rol(uint32_t value, int bits)
{
	/* return __builtin_rotateleft32(value, bits); */
	return (value << bits) | (value >> (32 - bits));
}

/* rotate 64-bit value left */
static inline uint64_t rol64(uint64_t value, int bits)
{
	/* return __builtin_rotateleft64(value, bits); */
	return (value << bits) | (value >> (64 - bits));
}

/* stack based allocation */
#ifndef alloca
#define alloca __builtin_alloca
#endif


/*
 * Key ladder.
 */
#ifndef __cplusplus
enum dcrypto_appid;      /* Forward declaration. */

int dcrypto_ladder_compute_usr(enum dcrypto_appid id,
			const uint32_t usr_salt[8]);
int dcrypto_ladder_derive(enum dcrypto_appid appid, const uint32_t salt[8],
			  const uint32_t input[8], uint32_t output[8]);
#endif

#ifdef __cplusplus
}
#endif

#endif  /* ! __EC_CHIP_G_DCRYPTO_INTERNAL_H */