Software APIs
p384.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_ECC_P384_H_
6 #define OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_ECC_P384_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
12 #include "sw/device/lib/crypto/drivers/otbn.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif // __cplusplus
17 
18 enum {
19  /**
20  * Length of a P-384 curve point coordinate in bits (modulo p).
21  */
22  kP384CoordBits = 384,
23  /**
24  * Length of a P-384 curve point coordinate in bytes.
25  */
26  kP384CoordBytes = kP384CoordBits / 8,
27  /**
28  * Length of a P-384 curve point coordinate in words.
29  */
30  kP384CoordWords = kP384CoordBytes / sizeof(uint32_t),
31  /**
32  * Length of an element in the P-384 scalar field (modulo the curve order n).
33  */
34  kP384ScalarBits = 384,
35  /**
36  * Length of a secret scalar share in bytes.
37  */
38  kP384ScalarBytes = kP384ScalarBits / 8,
39  /**
40  * Length of secret scalar share in words.
41  */
42  kP384ScalarWords = kP384ScalarBytes / sizeof(uint32_t),
43  /**
44  * Length of a masked secret scalar share.
45  *
46  * This implementation uses extra redundant bits for side-channel protection.
47  */
48  kP384MaskedScalarShareBits = kP384ScalarBits + 64,
49  /**
50  * Length of a masked secret scalar share in bytes.
51  */
52  kP384MaskedScalarShareBytes = kP384MaskedScalarShareBits / 8,
53  /**
54  * Length of masked secret scalar share in words.
55  */
56  kP384MaskedScalarShareWords = kP384MaskedScalarShareBytes / sizeof(uint32_t),
57 };
58 
59 /**
60  * A type that holds a masked value from the P-384 scalar field.
61  *
62  * This struct is used to represent secret keys, which are integers modulo n.
63  * The key d is represented in two 320-bit shares, d0 and d1, such that d = (d0
64  * + d1) mod n. Mathematically, d0 and d1 could also be reduced modulo n, but
65  * the extra bits provide side-channel protection.
66  */
67 typedef struct p384_masked_scalar {
68  /**
69  * First share of the secret scalar.
70  */
71  uint32_t share0[kP384MaskedScalarShareWords];
72  /**
73  * Second share of the secret scalar.
74  */
75  uint32_t share1[kP384MaskedScalarShareWords];
77 
78 /**
79  * A type that holds a P-384 curve point.
80  */
81 typedef struct p384_point {
82  /**
83  * Affine x-coordinate.
84  */
85  uint32_t x[kP384CoordWords];
86  /**
87  * Affine y-coordinate.
88  */
89  uint32_t y[kP384CoordWords];
90 } p384_point_t;
91 
92 /**
93  * A type that holds an ECDSA/P-384 signature.
94  *
95  * The signature consists of two integers r and s, computed modulo n.
96  */
97 typedef struct p384_ecdsa_signature_t {
98  uint32_t r[kP384ScalarWords];
99  uint32_t s[kP384ScalarWords];
101 
102 /**
103  * A type that holds a blinded ECDH shared secret key.
104  *
105  * The key is boolean-masked (XOR of the two shares).
106  */
107 typedef struct p384_ecdh_shared_key {
108  uint32_t share0[kP384CoordWords];
109  uint32_t share1[kP384CoordWords];
111 
112 /**
113  * Start an async P-384 keypair generation operation on OTBN.
114  *
115  * Appropriate for both ECDSA and ECDH; the key-generation process is the same.
116  *
117  * Returns an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
118  *
119  * @return Result of the operation (OK or error).
120  */
122 status_t p384_keygen_start(void);
123 
124 /**
125  * Finish an async P-384 keypair generation operation on OTBN.
126  *
127  * Blocks until OTBN is idle.
128  *
129  * @param[out] private_key Generated private key.
130  * @param[out] public_key Generated public key.
131  * @return Result of the operation (OK or error).
132  */
134 status_t p384_keygen_finalize(p384_masked_scalar_t *private_key,
135  p384_point_t *public_key);
136 
137 /**
138  * Start an async P-384 sideloaded keypair generation operation on OTBN.
139  *
140  * Appropriate for both ECDSA and ECDH; the key-generation process is the same.
141  *
142  * Expects a sideloaded key from keymgr to be already loaded on OTBN. Returns
143  * an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
144  *
145  * @return Result of the operation (OK or error).
146  */
148 status_t p384_sideload_keygen_start(void);
149 
150 /**
151  * Finish an async P-384 sideloaded keypair generation operation on OTBN.
152  *
153  * This routine will only read back the public key, instead of both public and
154  * private as with `p384_ecdsa_keygen_finalize`. Blocks until OTBN is idle.
155  *
156  * @param[out] public_key Public key.
157  * @return Result of the operation (OK or error).
158  */
160 status_t p384_sideload_keygen_finalize(p384_point_t *public_key);
161 
162 /**
163  * Start an async ECDSA/P-384 signature generation operation on OTBN.
164  *
165  * Returns an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
166  *
167  * @param digest Digest of the message to sign.
168  * @param private_key Secret key to sign the message with.
169  * @return Result of the operation (OK or error).
170  */
172 status_t p384_ecdsa_sign_start(const uint32_t digest[kP384ScalarWords],
173  const p384_masked_scalar_t *private_key);
174 
175 /**
176  * Start an async ECDSA/P-384 signature generation operation on OTBN.
177  *
178  * Expects a sideloaded key from keymgr to be already loaded on OTBN. Returns
179  * an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
180  *
181  * @param digest Digest of the message to sign.
182  * @return Result of the operation (OK or error).
183  */
185 status_t p384_ecdsa_sideload_sign_start(
186  const uint32_t digest[kP384ScalarWords]);
187 
188 /**
189  * Finish an async ECDSA/P-384 signature generation operation on OTBN.
190  *
191  * See the documentation of `p384_ecdsa_sign` for details.
192  *
193  * Blocks until OTBN is idle.
194  *
195  * @param[out] result Buffer in which to store the generated signature.
196  * @return Result of the operation (OK or error).
197  */
199 status_t p384_ecdsa_sign_finalize(p384_ecdsa_signature_t *result);
200 
201 /**
202  * Start an async ECDSA/P-384 signature verification operation on OTBN.
203  *
204  * See the documentation of `p384_ecdsa_verify` for details.
205  *
206  * Returns an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
207  *
208  * @param signature Signature to be verified.
209  * @param digest Digest of the message to check the signature against.
210  * @param public_key Key to check the signature against.
211  * @return Result of the operation (OK or error).
212  */
214 status_t p384_ecdsa_verify_start(const p384_ecdsa_signature_t *signature,
215  const uint32_t digest[kP384ScalarWords],
216  const p384_point_t *public_key);
217 
218 /**
219  * Finish an async ECDSA/P-384 signature verification operation on OTBN.
220  *
221  * See the documentation of `p384_ecdsa_verify` for details.
222  *
223  * Blocks until OTBN is idle.
224  *
225  * If the signature is valid, writes `kHardenedBoolTrue` to `result`;
226  * otherwise, writes `kHardenedBoolFalse`.
227  *
228  * Note: the caller must check the `result` buffer in order to determine if a
229  * signature passed verification. If a signature is invalid, but nothing goes
230  * wrong during computation (e.g. hardware errors, failed preconditions), the
231  * status will be OK but `result` will be `kHardenedBoolFalse`.
232  *
233  * @param signature Signature to be verified.
234  * @param[out] result Output buffer (true if signature is valid, false
235  * otherwise)
236  * @return Result of the operation (OK or error).
237  */
239 status_t p384_ecdsa_verify_finalize(const p384_ecdsa_signature_t *signature,
240  hardened_bool_t *result);
241 
242 /**
243  * Start an async ECDH/P-384 shared key generation operation on OTBN.
244  *
245  * Returns an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
246  *
247  * @param private_key Private key (d).
248  * @param public_key Public key (Q).
249  * @return Result of the operation (OK or error).
250  */
252 status_t p384_ecdh_start(const p384_masked_scalar_t *private_key,
253  const p384_point_t *public_key);
254 
255 /**
256  * Finish an async ECDH/P-384 shared key generation operation on OTBN.
257  *
258  * Blocks until OTBN is idle. May be used after either `p384_ecdh_start` or
259  * `p384_sideload_ecdh_start`; the operation is the same.
260  *
261  * @param[out] shared_key Shared secret key (x-coordinate of d*Q).
262  * @return Result of the operation (OK or error).
263  */
265 status_t p384_ecdh_finalize(p384_ecdh_shared_key_t *shared_key);
266 
267 /**
268  * Start an async ECDH/P-384 shared key generation operation on OTBN.
269  *
270  * Uses a private key generated from a key manager seed. The key manager should
271  * already have sideloaded the key into OTBN before this operation is called.
272  *
273  * Returns an `OTCRYPTO_ASYNC_INCOMPLETE` error if OTBN is busy.
274  *
275  * @param public_key Public key (Q).
276  * @return Result of the operation (OK or error).
277  */
279 status_t p384_sideload_ecdh_start(const p384_point_t *public_key);
280 
281 #ifdef __cplusplus
282 } // extern "C"
283 #endif // __cplusplus
284 
285 #endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_IMPL_ECC_P384_H_