@sproutboat/runtime 0.37.1 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1072 @@
1
+ /*
2
+ * crypto.subtle, native half. Compiled into the embedded transport (standalone binaries and
3
+ * sproutd), where BearSSL 0.6 (MIT) is already linked, and Monocypher 4.0.2 (BSD-2-Clause or
4
+ * CC0) supplies Ed25519 and X25519, which BearSSL does not have. See subtle/README.md.
5
+ *
6
+ * Nothing in this file does primitive math. RSA, ECDSA, hashes, HMAC and HKDF are BearSSL's;
7
+ * Ed25519 and X25519 are Monocypher's. What is here is composition (PKCS#1 PSS encoding,
8
+ * PBKDF2, key framing, DER for the key formats WebCrypto needs) and argument checking.
9
+ *
10
+ * One entry point, sbc_op(), so the JavaScript side marshals once: every argument and result is
11
+ * a byte string. Errors are small integers the JS side maps to DOMException names.
12
+ *
13
+ * No backslash-newline, backtick or dollar-brace here: the file is spliced into a JS template.
14
+ */
15
+
16
+ #define SBC_OK 0
17
+ #define SBC_DATA 1 /* DataError: the key bytes are not what the format says */
18
+ #define SBC_OPERATION 2 /* OperationError: the operation failed */
19
+ #define SBC_NOTSUP 3 /* NotSupportedError */
20
+
21
+ typedef unsigned char sbc_u8;
22
+
23
+ /* ---- randomness: the OS CSPRNG, behind BearSSL's PRNG interface ---------------------------- */
24
+
25
+ static int sbc_rand(void* out, size_t n) {
26
+ int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
27
+ if (fd < 0) return 0;
28
+ size_t got = 0;
29
+ while (got < n) {
30
+ ssize_t r = read(fd, (sbc_u8*)out + got, n - got);
31
+ if (r <= 0) { close(fd); return 0; }
32
+ got += (size_t)r;
33
+ }
34
+ close(fd);
35
+ return 1;
36
+ }
37
+ static void sbc_prng_init(const br_prng_class** c, const void* params, const void* seed, size_t len) { (void)c; (void)params; (void)seed; (void)len; }
38
+ static void sbc_prng_generate(const br_prng_class** c, void* out, size_t len) {
39
+ (void)c;
40
+ if (!sbc_rand(out, len)) abort(); /* no entropy: never hand back predictable key material */
41
+ }
42
+ static void sbc_prng_update(const br_prng_class** c, const void* seed, size_t len) { (void)c; (void)seed; (void)len; }
43
+ static const br_prng_class sbc_prng_vtable = { sizeof(br_prng_class*), sbc_prng_init, sbc_prng_generate, sbc_prng_update };
44
+ static const br_prng_class* sbc_prng = &sbc_prng_vtable;
45
+
46
+ /* ---- small helpers ------------------------------------------------------------------------- */
47
+
48
+ static const br_hash_class* sbc_hash(int bits) {
49
+ switch (bits) {
50
+ case 1: return &br_sha1_vtable;
51
+ case 256: return &br_sha256_vtable;
52
+ case 384: return &br_sha384_vtable;
53
+ case 512: return &br_sha512_vtable;
54
+ }
55
+ return 0;
56
+ }
57
+ static const unsigned char* sbc_hash_oid(int bits) {
58
+ switch (bits) {
59
+ case 1: return BR_HASH_OID_SHA1;
60
+ case 256: return BR_HASH_OID_SHA256;
61
+ case 384: return BR_HASH_OID_SHA384;
62
+ case 512: return BR_HASH_OID_SHA512;
63
+ }
64
+ return 0;
65
+ }
66
+ static size_t sbc_hlen(int bits) { return bits == 1 ? 20 : (size_t)bits / 8; }
67
+
68
+ /* One-shot hash: out holds sbc_hlen(bits) bytes. */
69
+ static int sbc_digest(int bits, const sbc_u8* m, size_t ml, sbc_u8* out) {
70
+ const br_hash_class* hc = sbc_hash(bits);
71
+ if (!hc) return 0;
72
+ br_hash_compat_context ctx;
73
+ hc->init(&ctx.vtable);
74
+ hc->update(&ctx.vtable, m, ml);
75
+ hc->out(&ctx.vtable, out);
76
+ return 1;
77
+ }
78
+
79
+ /* The parameter string: decimal numbers separated by commas. */
80
+ static long sbc_param(const sbc_u8* p, size_t pl, int idx) {
81
+ long v = 0; int cur = 0; int any = 0;
82
+ for (size_t i = 0; i <= pl; i++) {
83
+ if (i == pl || p[i] == ',') {
84
+ if (cur == idx) return any ? v : -1;
85
+ cur++; v = 0; any = 0;
86
+ } else if (p[i] >= '0' && p[i] <= '9') { v = v * 10 + (p[i] - '0'); any = 1; }
87
+ }
88
+ return -1;
89
+ }
90
+
91
+ static int sbc_ct_eq(const sbc_u8* a, const sbc_u8* b, size_t n) {
92
+ sbc_u8 d = 0;
93
+ for (size_t i = 0; i < n; i++) d |= (sbc_u8)(a[i] ^ b[i]);
94
+ return d == 0;
95
+ }
96
+
97
+ /* A growing output buffer. */
98
+ typedef struct { sbc_u8* p; size_t n; size_t cap; int bad; } sbc_buf;
99
+ static void sbc_put(sbc_buf* b, const void* d, size_t n) {
100
+ if (b->bad) return;
101
+ if (b->n + n > b->cap) {
102
+ size_t cap = b->cap ? b->cap : 256;
103
+ while (cap < b->n + n) cap *= 2;
104
+ sbc_u8* g = (sbc_u8*)realloc(b->p, cap);
105
+ if (!g) { b->bad = 1; return; }
106
+ b->p = g; b->cap = cap;
107
+ }
108
+ if (n) memcpy(b->p + b->n, d, n);
109
+ b->n += n;
110
+ }
111
+ static void sbc_put1(sbc_buf* b, sbc_u8 v) { sbc_put(b, &v, 1); }
112
+ /* A field: u32 big-endian length, then the bytes. */
113
+ static void sbc_field(sbc_buf* b, const void* d, size_t n) {
114
+ sbc_u8 h[4] = { (sbc_u8)(n >> 24), (sbc_u8)(n >> 16), (sbc_u8)(n >> 8), (sbc_u8)n };
115
+ sbc_put(b, h, 4); sbc_put(b, d, n);
116
+ }
117
+ /* The next field of a framed list, or 0 when the list is malformed. */
118
+ static int sbc_next(const sbc_u8** p, size_t* left, const sbc_u8** f, size_t* fl) {
119
+ if (*left < 4) return 0;
120
+ size_t n = ((size_t)(*p)[0] << 24) | ((size_t)(*p)[1] << 16) | ((size_t)(*p)[2] << 8) | (*p)[3];
121
+ if (n > *left - 4) return 0;
122
+ *f = *p + 4; *fl = n; *p += 4 + n; *left -= 4 + n;
123
+ return 1;
124
+ }
125
+ /* Big-endian integer with leading zeros stripped (a zero stays one zero byte, as DER wants it). */
126
+ static void sbc_strip(const sbc_u8** p, size_t* n) {
127
+ while (*n > 1 && **p == 0) { (*p)++; (*n)--; }
128
+ }
129
+
130
+ /* ---- DER ----------------------------------------------------------------------------------- */
131
+
132
+ static void sbc_der_len(sbc_buf* b, size_t n) {
133
+ if (n < 128) { sbc_put1(b, (sbc_u8)n); }
134
+ else if (n < 256) { sbc_put1(b, 0x81); sbc_put1(b, (sbc_u8)n); }
135
+ else if (n < 65536) { sbc_put1(b, 0x82); sbc_put1(b, (sbc_u8)(n >> 8)); sbc_put1(b, (sbc_u8)n); }
136
+ else { sbc_put1(b, 0x83); sbc_put1(b, (sbc_u8)(n >> 16)); sbc_put1(b, (sbc_u8)(n >> 8)); sbc_put1(b, (sbc_u8)n); }
137
+ }
138
+ static void sbc_der_tlv(sbc_buf* b, sbc_u8 tag, const void* d, size_t n) {
139
+ sbc_put1(b, tag); sbc_der_len(b, n); sbc_put(b, d, n);
140
+ }
141
+ /* A positive INTEGER from unsigned big-endian bytes. */
142
+ static void sbc_der_uint(sbc_buf* b, const sbc_u8* d, size_t n) {
143
+ sbc_strip(&d, &n);
144
+ sbc_put1(b, 0x02);
145
+ int pad = (d[0] & 0x80) ? 1 : 0;
146
+ sbc_der_len(b, n + (size_t)pad);
147
+ if (pad) sbc_put1(b, 0);
148
+ sbc_put(b, d, n);
149
+ }
150
+ /* Reads one TLV at *p; the content is [*c, *c + *cl). Definite lengths only. */
151
+ static int sbc_der_read(const sbc_u8** p, size_t* left, sbc_u8* tag, const sbc_u8** c, size_t* cl) {
152
+ if (*left < 2) return 0;
153
+ *tag = (*p)[0];
154
+ size_t n = (*p)[1], hl = 2;
155
+ if (n & 0x80) {
156
+ size_t k = n & 0x7f;
157
+ if (k == 0 || k > 3 || *left < 2 + k) return 0;
158
+ n = 0;
159
+ for (size_t i = 0; i < k; i++) n = (n << 8) | (*p)[2 + i];
160
+ hl = 2 + k;
161
+ }
162
+ if (n > *left - hl) return 0;
163
+ *c = *p + hl; *cl = n; *p += hl + n; *left -= hl + n;
164
+ return 1;
165
+ }
166
+
167
+ /* OID content bytes. */
168
+ static const sbc_u8 sbc_oid_rsa[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
169
+ static const sbc_u8 sbc_oid_ec[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 };
170
+ static const sbc_u8 sbc_oid_p256[] = { 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
171
+ static const sbc_u8 sbc_oid_p384[] = { 0x2b, 0x81, 0x04, 0x00, 0x22 };
172
+ static const sbc_u8 sbc_oid_p521[] = { 0x2b, 0x81, 0x04, 0x00, 0x23 };
173
+ static const sbc_u8 sbc_oid_ed25519[] = { 0x2b, 0x65, 0x70 };
174
+ static const sbc_u8 sbc_oid_x25519[] = { 0x2b, 0x65, 0x6e };
175
+
176
+ /* Key kinds, as the JS side sees them. */
177
+ #define SBC_K_RSA 1
178
+ #define SBC_K_EC 2
179
+ #define SBC_K_ED25519 3
180
+ #define SBC_K_X25519 4
181
+
182
+ static int sbc_oid_eq(const sbc_u8* a, size_t al, const sbc_u8* b, size_t bl) { return al == bl && memcmp(a, b, al) == 0; }
183
+
184
+ /* Curve codes used on the wire to JS: 1 = P-256, 2 = P-384, 3 = P-521. */
185
+ static int sbc_curve_br(int c) { return c == 1 ? BR_EC_secp256r1 : c == 2 ? BR_EC_secp384r1 : c == 3 ? BR_EC_secp521r1 : 0; }
186
+ static int sbc_curve_from_br(int c) { return c == BR_EC_secp256r1 ? 1 : c == BR_EC_secp384r1 ? 2 : c == BR_EC_secp521r1 ? 3 : 0; }
187
+ static size_t sbc_curve_size(int c) { return c == 1 ? 32 : c == 2 ? 48 : c == 3 ? 66 : 0; }
188
+ static void sbc_curve_oid(int c, const sbc_u8** o, size_t* n) {
189
+ if (c == 1) { *o = sbc_oid_p256; *n = sizeof sbc_oid_p256; }
190
+ else if (c == 2) { *o = sbc_oid_p384; *n = sizeof sbc_oid_p384; }
191
+ else { *o = sbc_oid_p521; *n = sizeof sbc_oid_p521; }
192
+ }
193
+
194
+ /* SubjectPublicKeyInfo -> kind, curve and key bytes. For RSA the bytes are the RSAPublicKey
195
+ * SEQUENCE content; for EC the uncompressed point; for the 25519 keys the 32 bytes. */
196
+ static int sbc_spki_parse(const sbc_u8* der, size_t len, int* kind, int* curve, const sbc_u8** key, size_t* keylen) {
197
+ const sbc_u8 *p = der, *c, *alg, *q;
198
+ size_t left = len, cl, algl, ql;
199
+ sbc_u8 t;
200
+ if (!sbc_der_read(&p, &left, &t, &c, &cl) || t != 0x30 || left != 0) return 0;
201
+ p = c; left = cl;
202
+ if (!sbc_der_read(&p, &left, &t, &alg, &algl) || t != 0x30) return 0;
203
+ if (!sbc_der_read(&p, &left, &t, &q, &ql) || t != 0x03 || left != 0 || ql < 1 || q[0] != 0) return 0;
204
+ *key = q + 1; *keylen = ql - 1;
205
+ const sbc_u8 *ap = alg, *oid, *par;
206
+ size_t al = algl, oidl, parl = 0;
207
+ if (!sbc_der_read(&ap, &al, &t, &oid, &oidl) || t != 0x06) return 0;
208
+ if (sbc_oid_eq(oid, oidl, sbc_oid_rsa, sizeof sbc_oid_rsa)) {
209
+ if (al) { if (!sbc_der_read(&ap, &al, &t, &par, &parl) || t != 0x05 || parl != 0 || al != 0) return 0; }
210
+ *kind = SBC_K_RSA; *curve = 0; return 1;
211
+ }
212
+ if (sbc_oid_eq(oid, oidl, sbc_oid_ec, sizeof sbc_oid_ec)) {
213
+ if (!sbc_der_read(&ap, &al, &t, &par, &parl) || t != 0x06 || al != 0) return 0;
214
+ int cv = 0;
215
+ if (sbc_oid_eq(par, parl, sbc_oid_p256, sizeof sbc_oid_p256)) cv = 1;
216
+ else if (sbc_oid_eq(par, parl, sbc_oid_p384, sizeof sbc_oid_p384)) cv = 2;
217
+ else if (sbc_oid_eq(par, parl, sbc_oid_p521, sizeof sbc_oid_p521)) cv = 3;
218
+ if (!cv || *keylen != 1 + 2 * sbc_curve_size(cv) || (*key)[0] != 4) return 0;
219
+ *kind = SBC_K_EC; *curve = cv; return 1;
220
+ }
221
+ if (al == 0 && *keylen == 32) {
222
+ if (sbc_oid_eq(oid, oidl, sbc_oid_ed25519, 3)) { *kind = SBC_K_ED25519; *curve = 0; return 1; }
223
+ if (sbc_oid_eq(oid, oidl, sbc_oid_x25519, 3)) { *kind = SBC_K_X25519; *curve = 0; return 1; }
224
+ }
225
+ return 0;
226
+ }
227
+
228
+ /* Wrap an algorithm identifier body and a key in a SubjectPublicKeyInfo. */
229
+ static void sbc_spki_build(sbc_buf* out, const sbc_buf* alg, const sbc_u8* key, size_t keylen) {
230
+ sbc_buf bits = {0}, body = {0};
231
+ sbc_put1(&bits, 0); sbc_put(&bits, key, keylen);
232
+ sbc_der_tlv(&body, 0x30, alg->p, alg->n);
233
+ sbc_der_tlv(&body, 0x03, bits.p, bits.n);
234
+ sbc_der_tlv(out, 0x30, body.p, body.n);
235
+ free(bits.p); free(body.p);
236
+ if (bits.bad || body.bad) out->bad = 1;
237
+ }
238
+ static void sbc_alg_rsa(sbc_buf* a) { sbc_der_tlv(a, 0x06, sbc_oid_rsa, sizeof sbc_oid_rsa); sbc_der_tlv(a, 0x05, 0, 0); }
239
+ static void sbc_alg_ec(sbc_buf* a, int curve) {
240
+ const sbc_u8* o; size_t n;
241
+ sbc_curve_oid(curve, &o, &n);
242
+ sbc_der_tlv(a, 0x06, sbc_oid_ec, sizeof sbc_oid_ec);
243
+ sbc_der_tlv(a, 0x06, o, n);
244
+ }
245
+
246
+ /* ---- key decoding -------------------------------------------------------------------------- */
247
+
248
+ /* PKCS#8 for Ed25519 and X25519: SEQ { INT 0, SEQ { OID }, OCTET STRING { OCTET STRING seed } }. */
249
+ static int sbc_pkcs8_okp(const sbc_u8* der, size_t len, int* kind, const sbc_u8** seed) {
250
+ const sbc_u8 *p = der, *c, *q;
251
+ size_t left = len, cl, ql;
252
+ sbc_u8 t;
253
+ if (!sbc_der_read(&p, &left, &t, &c, &cl) || t != 0x30 || left != 0) return 0;
254
+ p = c; left = cl;
255
+ if (!sbc_der_read(&p, &left, &t, &q, &ql) || t != 0x02 || ql != 1 || q[0] != 0) return 0;
256
+ if (!sbc_der_read(&p, &left, &t, &q, &ql) || t != 0x30) return 0;
257
+ {
258
+ const sbc_u8 *ap = q, *oid; size_t al = ql, oidl;
259
+ if (!sbc_der_read(&ap, &al, &t, &oid, &oidl) || t != 0x06 || al != 0) return 0;
260
+ if (sbc_oid_eq(oid, oidl, sbc_oid_ed25519, 3)) *kind = SBC_K_ED25519;
261
+ else if (sbc_oid_eq(oid, oidl, sbc_oid_x25519, 3)) *kind = SBC_K_X25519;
262
+ else return 0;
263
+ }
264
+ if (!sbc_der_read(&p, &left, &t, &q, &ql) || t != 0x04) return 0; /* trailing attributes are ignored */
265
+ {
266
+ const sbc_u8 *ip = q, *s; size_t il = ql, sl;
267
+ if (!sbc_der_read(&ip, &il, &t, &s, &sl) || t != 0x04 || sl != 32 || il != 0) return 0;
268
+ *seed = s;
269
+ }
270
+ return 1;
271
+ }
272
+
273
+ /* The exact bit length of an unsigned big-endian integer. */
274
+ static uint32_t sbc_bitlen(const sbc_u8* d, size_t n) {
275
+ while (n > 0 && *d == 0) { d++; n--; }
276
+ if (n == 0) return 0;
277
+ uint32_t bits = (uint32_t)(n * 8);
278
+ for (sbc_u8 top = d[0]; !(top & 0x80); top = (sbc_u8)(top << 1)) bits--;
279
+ return bits;
280
+ }
281
+
282
+ /* An RSA private key as PKCS#8 carries it. BearSSL has a decoder for this, but it drops the public
283
+ * exponent and recomputes it, which only works for primes that are 3 mod 4: BoringSSL and OpenSSL
284
+ * keys often are not. So the structure is read here, and BearSSL gets the CRT parts. */
285
+ typedef struct {
286
+ const sbc_u8 *n, *e, *d, *p, *q, *dp, *dq, *qi;
287
+ size_t nl, el, dl, pl, ql, dpl, dql, qil;
288
+ } sbc_rsa_fields;
289
+ static int sbc_rsa_parse_pkcs8(const sbc_u8* der, size_t len, sbc_rsa_fields* k) {
290
+ const sbc_u8 *p = der, *c, *q;
291
+ size_t left = len, cl, ql;
292
+ sbc_u8 t;
293
+ if (!sbc_der_read(&p, &left, &t, &c, &cl) || t != 0x30 || left != 0) return 0;
294
+ p = c; left = cl;
295
+ if (!sbc_der_read(&p, &left, &t, &q, &ql) || t != 0x02 || ql != 1 || q[0] != 0) return 0;
296
+ if (!sbc_der_read(&p, &left, &t, &q, &ql) || t != 0x30) return 0;
297
+ {
298
+ const sbc_u8 *ap = q, *oid; size_t al = ql, oidl;
299
+ if (!sbc_der_read(&ap, &al, &t, &oid, &oidl) || t != 0x06 || !sbc_oid_eq(oid, oidl, sbc_oid_rsa, sizeof sbc_oid_rsa)) return 0;
300
+ }
301
+ if (!sbc_der_read(&p, &left, &t, &q, &ql) || t != 0x04) return 0;
302
+ {
303
+ const sbc_u8 *sp = q; size_t sl = ql;
304
+ if (!sbc_der_read(&sp, &sl, &t, &c, &cl) || t != 0x30 || sl != 0) return 0;
305
+ sp = c; sl = cl;
306
+ if (!sbc_der_read(&sp, &sl, &t, &q, &ql) || t != 0x02 || ql != 1 || q[0] != 0) return 0;
307
+ const sbc_u8** f[8] = { &k->n, &k->e, &k->d, &k->p, &k->q, &k->dp, &k->dq, &k->qi };
308
+ size_t* fl[8] = { &k->nl, &k->el, &k->dl, &k->pl, &k->ql, &k->dpl, &k->dql, &k->qil };
309
+ for (int i = 0; i < 8; i++) {
310
+ if (!sbc_der_read(&sp, &sl, &t, f[i], fl[i]) || t != 0x02 || *fl[i] == 0 || ((*f[i])[0] & 0x80)) return 0;
311
+ sbc_strip(f[i], fl[i]);
312
+ }
313
+ }
314
+ if (sbc_bitlen(k->n, k->nl) < 512 || sbc_bitlen(k->n, k->nl) > 4096) return 0;
315
+ return 1;
316
+ }
317
+ static void sbc_rsa_bear_key(const sbc_rsa_fields* k, br_rsa_private_key* sk) {
318
+ sk->n_bitlen = sbc_bitlen(k->n, k->nl);
319
+ sk->p = (sbc_u8*)k->p; sk->plen = k->pl; sk->q = (sbc_u8*)k->q; sk->qlen = k->ql;
320
+ sk->dp = (sbc_u8*)k->dp; sk->dplen = k->dpl; sk->dq = (sbc_u8*)k->dq; sk->dqlen = k->dql;
321
+ sk->iq = (sbc_u8*)k->qi; sk->iqlen = k->qil;
322
+ }
323
+
324
+ /* Decode a PKCS#8 or SPKI blob into fields JS turns into a JWK.
325
+ * Result: [kind u8][curve u8][u8 is_private] then fields.
326
+ * RSA public: n e RSA private: n e d p q dp dq qi
327
+ * EC public: point EC private: point scalar
328
+ * 25519 public: key 25519 private: key seed */
329
+ static int sbc_decode(int pkcs8, const sbc_u8* der, size_t len, sbc_buf* out) {
330
+ int kind = 0, curve = 0;
331
+ if (!pkcs8) {
332
+ const sbc_u8* key; size_t kl;
333
+ if (!sbc_spki_parse(der, len, &kind, &curve, &key, &kl)) return SBC_DATA;
334
+ sbc_put1(out, (sbc_u8)kind); sbc_put1(out, (sbc_u8)curve); sbc_put1(out, 0);
335
+ if (kind == SBC_K_RSA) {
336
+ const sbc_u8 *p = key, *c, *n, *e; size_t left = kl, cl, nl, el; sbc_u8 t;
337
+ if (!sbc_der_read(&p, &left, &t, &c, &cl) || t != 0x30 || left != 0) return SBC_DATA;
338
+ p = c; left = cl;
339
+ if (!sbc_der_read(&p, &left, &t, &n, &nl) || t != 0x02 || !sbc_der_read(&p, &left, &t, &e, &el) || t != 0x02 || left != 0) return SBC_DATA;
340
+ sbc_strip(&n, &nl); sbc_strip(&e, &el);
341
+ if (nl == 0 || el == 0 || (n[0] & 0x80 && 0)) return SBC_DATA;
342
+ sbc_field(out, n, nl); sbc_field(out, e, el);
343
+ } else {
344
+ sbc_field(out, key, kl);
345
+ }
346
+ return SBC_OK;
347
+ }
348
+ {
349
+ const sbc_u8* seed;
350
+ if (sbc_pkcs8_okp(der, len, &kind, &seed)) {
351
+ sbc_u8 sk[64], pk[32], s[32];
352
+ memcpy(s, seed, 32);
353
+ if (kind == SBC_K_ED25519) crypto_ed25519_key_pair(sk, pk, s);
354
+ else crypto_x25519_public_key(pk, seed);
355
+ sbc_put1(out, (sbc_u8)kind); sbc_put1(out, 0); sbc_put1(out, 1);
356
+ sbc_field(out, pk, 32); sbc_field(out, seed, 32);
357
+ return SBC_OK;
358
+ }
359
+ }
360
+ {
361
+ sbc_rsa_fields k;
362
+ if (sbc_rsa_parse_pkcs8(der, len, &k)) {
363
+ sbc_put1(out, SBC_K_RSA); sbc_put1(out, 0); sbc_put1(out, 1);
364
+ sbc_field(out, k.n, k.nl); sbc_field(out, k.e, k.el); sbc_field(out, k.d, k.dl);
365
+ sbc_field(out, k.p, k.pl); sbc_field(out, k.q, k.ql);
366
+ sbc_field(out, k.dp, k.dpl); sbc_field(out, k.dq, k.dql); sbc_field(out, k.qi, k.qil);
367
+ return SBC_OK;
368
+ }
369
+ }
370
+ {
371
+ br_skey_decoder_context* dc = (br_skey_decoder_context*)malloc(sizeof *dc);
372
+ if (!dc) return SBC_OPERATION;
373
+ br_skey_decoder_init(dc);
374
+ br_skey_decoder_push(dc, der, len);
375
+ int ty = br_skey_decoder_key_type(dc);
376
+ int rc = SBC_DATA;
377
+ if (ty == BR_KEYTYPE_EC) {
378
+ const br_ec_private_key* sk = br_skey_decoder_get_ec(dc);
379
+ int cv = sbc_curve_from_br(sk->curve);
380
+ if (cv) {
381
+ sbc_u8 pub[133];
382
+ br_ec_public_key pk;
383
+ if (br_ec_compute_pub(br_ec_get_default(), &pk, pub, sk) != 0) {
384
+ sbc_put1(out, SBC_K_EC); sbc_put1(out, (sbc_u8)cv); sbc_put1(out, 1);
385
+ sbc_field(out, pk.q, pk.qlen);
386
+ /* The scalar, left padded to the field size as JWK d wants it. */
387
+ size_t fs = sbc_curve_size(cv);
388
+ sbc_u8 d[66]; const sbc_u8* xs = sk->x; size_t xl = sk->xlen;
389
+ while (xl > fs && *xs == 0) { xs++; xl--; }
390
+ if (xl <= fs) {
391
+ memset(d, 0, fs - xl); memcpy(d + fs - xl, xs, xl);
392
+ sbc_field(out, d, fs);
393
+ rc = SBC_OK;
394
+ }
395
+ }
396
+ }
397
+ }
398
+ free(dc);
399
+ return rc;
400
+ }
401
+ }
402
+
403
+ /* ---- key encoding -------------------------------------------------------------------------- */
404
+
405
+ /* The inverse of sbc_decode for the fields JS has after reading a JWK or generating a key.
406
+ * kind, curve in params. fields: see sbc_decode. */
407
+ static int sbc_encode(int pkcs8, int kind, int curve, const sbc_u8* f, size_t fl, sbc_buf* out) {
408
+ const sbc_u8 *a, *b, *c, *d, *e, *g, *h, *i;
409
+ size_t al, bl, cl, dl, el, gl, hl, il;
410
+ const sbc_u8* p = f; size_t left = fl;
411
+ if (kind == SBC_K_RSA) {
412
+ if (!sbc_next(&p, &left, &a, &al) || !sbc_next(&p, &left, &b, &bl)) return SBC_DATA; /* n e */
413
+ sbc_strip(&a, &al); sbc_strip(&b, &bl);
414
+ if (!pkcs8) {
415
+ sbc_buf alg = {0}, key = {0}, seq = {0};
416
+ sbc_alg_rsa(&alg);
417
+ sbc_der_uint(&seq, a, al); sbc_der_uint(&seq, b, bl);
418
+ sbc_der_tlv(&key, 0x30, seq.p, seq.n);
419
+ sbc_spki_build(out, &alg, key.p, key.n);
420
+ free(alg.p); free(key.p); free(seq.p);
421
+ return SBC_OK;
422
+ }
423
+ if (!sbc_next(&p, &left, &c, &cl) || !sbc_next(&p, &left, &d, &dl) || !sbc_next(&p, &left, &e, &el) ||
424
+ !sbc_next(&p, &left, &g, &gl) || !sbc_next(&p, &left, &h, &hl) || !sbc_next(&p, &left, &i, &il)) return SBC_DATA; /* d p q dp dq qi */
425
+ br_rsa_private_key sk; br_rsa_public_key pk;
426
+ sbc_strip(&d, &dl); sbc_strip(&e, &el); sbc_strip(&g, &gl); sbc_strip(&h, &hl); sbc_strip(&i, &il);
427
+ /* BearSSL's encoder wants the modulus bit length to be exact. */
428
+ uint32_t bits = (uint32_t)(al * 8);
429
+ { sbc_u8 top = a[0]; while (!(top & 0x80)) { bits--; top = (sbc_u8)(top << 1); } }
430
+ sk.n_bitlen = bits;
431
+ sk.p = (sbc_u8*)d; sk.plen = dl; sk.q = (sbc_u8*)e; sk.qlen = el;
432
+ sk.dp = (sbc_u8*)g; sk.dplen = gl; sk.dq = (sbc_u8*)h; sk.dqlen = hl; sk.iq = (sbc_u8*)i; sk.iqlen = il;
433
+ pk.n = (sbc_u8*)a; pk.nlen = al; pk.e = (sbc_u8*)b; pk.elen = bl;
434
+ size_t need = br_encode_rsa_pkcs8_der(0, &sk, &pk, c, cl);
435
+ sbc_u8* dst = (sbc_u8*)malloc(need);
436
+ if (!dst) return SBC_OPERATION;
437
+ br_encode_rsa_pkcs8_der(dst, &sk, &pk, c, cl);
438
+ sbc_put(out, dst, need);
439
+ free(dst);
440
+ return SBC_OK;
441
+ }
442
+ if (kind == SBC_K_EC) {
443
+ size_t fs = sbc_curve_size(curve);
444
+ if (!fs || !sbc_next(&p, &left, &a, &al)) return SBC_DATA; /* point */
445
+ if (!pkcs8) {
446
+ if (al != 1 + 2 * fs || a[0] != 4) return SBC_DATA;
447
+ sbc_buf alg = {0};
448
+ sbc_alg_ec(&alg, curve);
449
+ sbc_spki_build(out, &alg, a, al);
450
+ free(alg.p);
451
+ return SBC_OK;
452
+ }
453
+ if (!sbc_next(&p, &left, &b, &bl) || bl != fs) return SBC_DATA; /* scalar */
454
+ br_ec_private_key sk; br_ec_public_key pk;
455
+ sk.curve = sbc_curve_br(curve); sk.x = (sbc_u8*)b; sk.xlen = bl;
456
+ pk.curve = sk.curve; pk.q = (sbc_u8*)a; pk.qlen = al;
457
+ size_t need = br_encode_ec_pkcs8_der(0, &sk, &pk);
458
+ sbc_u8* dst = (sbc_u8*)malloc(need);
459
+ if (!dst) return SBC_OPERATION;
460
+ br_encode_ec_pkcs8_der(dst, &sk, &pk);
461
+ sbc_put(out, dst, need);
462
+ free(dst);
463
+ return SBC_OK;
464
+ }
465
+ if (kind == SBC_K_ED25519 || kind == SBC_K_X25519) {
466
+ const sbc_u8* oid = kind == SBC_K_ED25519 ? sbc_oid_ed25519 : sbc_oid_x25519;
467
+ if (!sbc_next(&p, &left, &a, &al) || al != 32) return SBC_DATA; /* public key */
468
+ sbc_buf alg = {0};
469
+ sbc_der_tlv(&alg, 0x06, oid, 3);
470
+ if (!pkcs8) { sbc_spki_build(out, &alg, a, al); free(alg.p); return SBC_OK; }
471
+ if (!sbc_next(&p, &left, &b, &bl) || bl != 32) { free(alg.p); return SBC_DATA; } /* seed */
472
+ sbc_buf inner = {0}, wrap = {0}, body = {0};
473
+ sbc_der_tlv(&inner, 0x04, b, 32);
474
+ sbc_der_tlv(&wrap, 0x04, inner.p, inner.n);
475
+ sbc_put1(&body, 0x02); sbc_put1(&body, 1); sbc_put1(&body, 0);
476
+ sbc_der_tlv(&body, 0x30, alg.p, alg.n);
477
+ sbc_put(&body, wrap.p, wrap.n);
478
+ sbc_der_tlv(out, 0x30, body.p, body.n);
479
+ free(alg.p); free(inner.p); free(wrap.p); free(body.p);
480
+ return SBC_OK;
481
+ }
482
+ return SBC_NOTSUP;
483
+ }
484
+
485
+ /* ---- HMAC, PBKDF2, HKDF -------------------------------------------------------------------- */
486
+
487
+ static void sbc_hmac(int bits, const sbc_u8* key, size_t kl, const sbc_u8* m, size_t ml, sbc_u8* out) {
488
+ br_hmac_key_context kc; br_hmac_context hc;
489
+ br_hmac_key_init(&kc, sbc_hash(bits), key, kl);
490
+ br_hmac_init(&hc, &kc, 0);
491
+ br_hmac_update(&hc, m, ml);
492
+ br_hmac_out(&hc, out);
493
+ }
494
+
495
+ /* RFC 8018 PBKDF2 over HMAC(bits). */
496
+ static int sbc_pbkdf2(int bits, const sbc_u8* pw, size_t pl, const sbc_u8* salt, size_t sl, uint32_t iters, sbc_u8* out, size_t len) {
497
+ size_t hl = sbc_hlen(bits);
498
+ br_hmac_key_context kc;
499
+ br_hmac_key_init(&kc, sbc_hash(bits), pw, pl);
500
+ sbc_u8 u[64], t[64];
501
+ for (uint32_t blk = 1; len > 0; blk++) {
502
+ br_hmac_context hc;
503
+ sbc_u8 be[4] = { (sbc_u8)(blk >> 24), (sbc_u8)(blk >> 16), (sbc_u8)(blk >> 8), (sbc_u8)blk };
504
+ br_hmac_init(&hc, &kc, 0); br_hmac_update(&hc, salt, sl); br_hmac_update(&hc, be, 4); br_hmac_out(&hc, u);
505
+ memcpy(t, u, hl);
506
+ for (uint32_t i = 1; i < iters; i++) {
507
+ br_hmac_init(&hc, &kc, 0); br_hmac_update(&hc, u, hl); br_hmac_out(&hc, u);
508
+ for (size_t j = 0; j < hl; j++) t[j] ^= u[j];
509
+ }
510
+ size_t n = len < hl ? len : hl;
511
+ memcpy(out, t, n); out += n; len -= n;
512
+ }
513
+ return 1;
514
+ }
515
+
516
+ static int sbc_hkdf(int bits, const sbc_u8* ikm, size_t il, const sbc_u8* salt, size_t sl, const sbc_u8* info, size_t nl, sbc_u8* out, size_t len) {
517
+ br_hkdf_context hc;
518
+ br_hkdf_init(&hc, sbc_hash(bits), salt, sl);
519
+ br_hkdf_inject(&hc, ikm, il);
520
+ br_hkdf_flip(&hc);
521
+ br_hkdf_produce(&hc, info, nl, out, len);
522
+ return 1;
523
+ }
524
+
525
+ /* ---- RSA ----------------------------------------------------------------------------------- */
526
+
527
+ static int sbc_load_rsa_public(const sbc_u8* der, size_t len, br_rsa_public_key* pk) {
528
+ int kind, curve; const sbc_u8* key; size_t kl;
529
+ if (!sbc_spki_parse(der, len, &kind, &curve, &key, &kl) || kind != SBC_K_RSA) return 0;
530
+ const sbc_u8 *p = key, *c, *n, *e; size_t left = kl, cl, nl, el; sbc_u8 t;
531
+ if (!sbc_der_read(&p, &left, &t, &c, &cl) || t != 0x30) return 0;
532
+ p = c; left = cl;
533
+ if (!sbc_der_read(&p, &left, &t, &n, &nl) || t != 0x02 || !sbc_der_read(&p, &left, &t, &e, &el) || t != 0x02) return 0;
534
+ sbc_strip(&n, &nl); sbc_strip(&e, &el);
535
+ pk->n = (sbc_u8*)n; pk->nlen = nl; pk->e = (sbc_u8*)e; pk->elen = el;
536
+ return 1;
537
+ }
538
+
539
+ static int sbc_rsa_pkcs1_sign(int bits, const sbc_u8* key, size_t kl, const sbc_u8* m, size_t ml, sbc_buf* out) {
540
+ sbc_rsa_fields kf; br_rsa_private_key skv; const br_rsa_private_key* sk = &skv;
541
+ if (!sbc_rsa_parse_pkcs8(key, kl, &kf)) return SBC_DATA;
542
+ sbc_rsa_bear_key(&kf, &skv);
543
+ sbc_u8 h[64], x[512];
544
+ size_t xl = (sk->n_bitlen + 7) / 8;
545
+ int rc = SBC_OPERATION;
546
+ if (xl <= sizeof x && sbc_digest(bits, m, ml, h) &&
547
+ br_rsa_pkcs1_sign_get_default()(sbc_hash_oid(bits), h, sbc_hlen(bits), sk, x)) {
548
+ sbc_put(out, x, xl); rc = SBC_OK;
549
+ }
550
+ return rc;
551
+ }
552
+ static int sbc_rsa_pkcs1_verify(int bits, const sbc_u8* key, size_t kl, const sbc_u8* sig, size_t sl, const sbc_u8* m, size_t ml, int* ok) {
553
+ br_rsa_public_key pk;
554
+ *ok = 0;
555
+ if (!sbc_load_rsa_public(key, kl, &pk)) return SBC_DATA;
556
+ sbc_u8 h[64], x[512], got[64];
557
+ if (sl != pk.nlen || sl > sizeof x) return SBC_OK;
558
+ memcpy(x, sig, sl);
559
+ if (!sbc_digest(bits, m, ml, h)) return SBC_NOTSUP;
560
+ if (br_rsa_pkcs1_vrfy_get_default()(x, sl, sbc_hash_oid(bits), sbc_hlen(bits), &pk, got) && sbc_ct_eq(got, h, sbc_hlen(bits))) *ok = 1;
561
+ return SBC_OK;
562
+ }
563
+
564
+ /* MGF1 (RFC 8017 B.2.1): XOR the mask for seed into out. */
565
+ static void sbc_mgf1_xor(int bits, const sbc_u8* seed, size_t sl, sbc_u8* out, size_t len) {
566
+ sbc_u8 h[64];
567
+ size_t hl = sbc_hlen(bits);
568
+ const br_hash_class* hc = sbc_hash(bits);
569
+ for (uint32_t ctr = 0; len > 0; ctr++) {
570
+ br_hash_compat_context ctx;
571
+ sbc_u8 be[4] = { (sbc_u8)(ctr >> 24), (sbc_u8)(ctr >> 16), (sbc_u8)(ctr >> 8), (sbc_u8)ctr };
572
+ hc->init(&ctx.vtable); hc->update(&ctx.vtable, seed, sl); hc->update(&ctx.vtable, be, 4); hc->out(&ctx.vtable, h);
573
+ size_t n = len < hl ? len : hl;
574
+ for (size_t i = 0; i < n; i++) out[i] ^= h[i];
575
+ out += n; len -= n;
576
+ }
577
+ }
578
+
579
+ /* H(0x00*8 || mHash || salt) */
580
+ static void sbc_pss_h(int bits, const sbc_u8* mh, const sbc_u8* salt, size_t saltlen, sbc_u8* out) {
581
+ const br_hash_class* hc = sbc_hash(bits);
582
+ br_hash_compat_context ctx;
583
+ sbc_u8 zero[8] = {0};
584
+ hc->init(&ctx.vtable); hc->update(&ctx.vtable, zero, 8); hc->update(&ctx.vtable, mh, sbc_hlen(bits)); hc->update(&ctx.vtable, salt, saltlen); hc->out(&ctx.vtable, out);
585
+ }
586
+
587
+ /* RSASSA-PSS with MGF1 over the same hash (RFC 8017 9.1). */
588
+ static int sbc_rsa_pss_sign(int bits, size_t saltlen, const sbc_u8* key, size_t kl, const sbc_u8* m, size_t ml, sbc_buf* out) {
589
+ sbc_rsa_fields kf; br_rsa_private_key skv; const br_rsa_private_key* sk = &skv;
590
+ if (!sbc_rsa_parse_pkcs8(key, kl, &kf)) return SBC_DATA;
591
+ sbc_rsa_bear_key(&kf, &skv);
592
+ int rc = SBC_OPERATION;
593
+ size_t k = (sk->n_bitlen + 7) / 8, emBits = sk->n_bitlen - 1, emLen = (emBits + 7) / 8, hl = sbc_hlen(bits);
594
+ sbc_u8 x[512], mh[64], salt[512], hh[64];
595
+ if (k <= sizeof x && saltlen <= sizeof salt && emLen >= hl + saltlen + 2 && sbc_digest(bits, m, ml, mh) &&
596
+ (saltlen == 0 || sbc_rand(salt, saltlen))) {
597
+ memset(x, 0, sizeof x);
598
+ sbc_u8* em = x + (k - emLen);
599
+ size_t dbl = emLen - hl - 1;
600
+ sbc_pss_h(bits, mh, salt, saltlen, hh);
601
+ em[dbl - saltlen - 1] = 1;
602
+ memcpy(em + dbl - saltlen, salt, saltlen);
603
+ sbc_mgf1_xor(bits, hh, hl, em, dbl);
604
+ em[0] &= (sbc_u8)(0xff >> (8 * emLen - emBits));
605
+ memcpy(em + dbl, hh, hl);
606
+ em[emLen - 1] = 0xbc;
607
+ if (br_rsa_private_get_default()(x, sk)) { sbc_put(out, x, k); rc = SBC_OK; }
608
+ }
609
+ return rc;
610
+ }
611
+ static int sbc_rsa_pss_verify(int bits, size_t saltlen, const sbc_u8* key, size_t kl, const sbc_u8* sig, size_t sl, const sbc_u8* m, size_t ml, int* ok) {
612
+ br_rsa_public_key pk;
613
+ *ok = 0;
614
+ if (!sbc_load_rsa_public(key, kl, &pk)) return SBC_DATA;
615
+ size_t k = pk.nlen, hl = sbc_hlen(bits);
616
+ sbc_u8 x[512], mh[64], hh[64], db[512];
617
+ if (sl != k || k > sizeof x) return SBC_OK;
618
+ /* Exact modulus bit length. */
619
+ uint32_t nbits = (uint32_t)(k * 8);
620
+ { sbc_u8 top = pk.n[0]; while (top && !(top & 0x80)) { nbits--; top = (sbc_u8)(top << 1); } }
621
+ size_t emBits = nbits - 1, emLen = (emBits + 7) / 8;
622
+ memcpy(x, sig, sl);
623
+ if (!br_rsa_public_get_default()(x, k, &pk)) return SBC_OK;
624
+ if (!sbc_digest(bits, m, ml, mh)) return SBC_NOTSUP;
625
+ if (emLen < hl + saltlen + 2) return SBC_OK;
626
+ const sbc_u8* em = x + (k - emLen);
627
+ if (k > emLen && x[0] != 0) return SBC_OK;
628
+ if (em[emLen - 1] != 0xbc) return SBC_OK;
629
+ size_t dbl = emLen - hl - 1;
630
+ if (dbl > sizeof db) return SBC_OK;
631
+ memcpy(db, em, dbl);
632
+ if (db[0] & (sbc_u8)~(0xff >> (8 * emLen - emBits))) return SBC_OK;
633
+ sbc_mgf1_xor(bits, em + dbl, hl, db, dbl);
634
+ db[0] &= (sbc_u8)(0xff >> (8 * emLen - emBits));
635
+ size_t ps = dbl - saltlen - 1;
636
+ for (size_t i = 0; i < ps; i++) if (db[i] != 0) return SBC_OK;
637
+ if (db[ps] != 1) return SBC_OK;
638
+ sbc_pss_h(bits, mh, db + ps + 1, saltlen, hh);
639
+ if (sbc_ct_eq(hh, em + dbl, hl)) *ok = 1;
640
+ return SBC_OK;
641
+ }
642
+
643
+ static int sbc_rsa_keygen(unsigned modbits, uint32_t pubexp, sbc_buf* out) {
644
+ if (modbits < 512 || modbits > 4096 || (pubexp != 3 && pubexp != 65537)) return SBC_NOTSUP;
645
+ br_rsa_private_key sk; br_rsa_public_key pk;
646
+ sbc_u8 kpriv[BR_RSA_KBUF_PRIV_SIZE(4096)], kpub[BR_RSA_KBUF_PUB_SIZE(4096)];
647
+ br_rsa_keygen kg = br_rsa_keygen_get_default();
648
+ if (!kg(&sbc_prng, &sk, kpriv, &pk, kpub, modbits, pubexp)) return SBC_OPERATION;
649
+ size_t dl = br_rsa_compute_privexp_get_default()(0, &sk, pubexp);
650
+ sbc_u8* d = (sbc_u8*)malloc(dl ? dl : 1);
651
+ if (!d) return SBC_OPERATION;
652
+ br_rsa_compute_privexp_get_default()(d, &sk, pubexp);
653
+ size_t need = br_encode_rsa_pkcs8_der(0, &sk, &pk, d, dl);
654
+ sbc_u8* dst = (sbc_u8*)malloc(need);
655
+ if (dst) { br_encode_rsa_pkcs8_der(dst, &sk, &pk, d, dl); sbc_put(out, dst, need); }
656
+ free(dst); free(d);
657
+ memset(kpriv, 0, sizeof kpriv);
658
+ return dst ? SBC_OK : SBC_OPERATION;
659
+ }
660
+
661
+ /* ---- ECDSA --------------------------------------------------------------------------------- */
662
+
663
+ static int sbc_ec_load_private(const sbc_u8* der, size_t len, br_skey_decoder_context** dcp, const br_ec_private_key** sk) {
664
+ br_skey_decoder_context* dc = (br_skey_decoder_context*)malloc(sizeof *dc);
665
+ if (!dc) return SBC_OPERATION;
666
+ br_skey_decoder_init(dc);
667
+ br_skey_decoder_push(dc, der, len);
668
+ *sk = br_skey_decoder_get_ec(dc);
669
+ if (!*sk || !sbc_curve_from_br((*sk)->curve)) { free(dc); return SBC_DATA; }
670
+ *dcp = dc;
671
+ return SBC_OK;
672
+ }
673
+ static int sbc_ecdsa_sign(int bits, const sbc_u8* key, size_t kl, const sbc_u8* m, size_t ml, sbc_buf* out) {
674
+ br_skey_decoder_context* dc; const br_ec_private_key* sk;
675
+ int rc = sbc_ec_load_private(key, kl, &dc, &sk);
676
+ if (rc != SBC_OK) return rc;
677
+ sbc_u8 h[64], sig[132];
678
+ rc = SBC_OPERATION;
679
+ if (sbc_digest(bits, m, ml, h)) {
680
+ size_t n = br_ecdsa_sign_raw_get_default()(br_ec_get_default(), sbc_hash(bits), h, sk, sig);
681
+ if (n) { sbc_put(out, sig, n); rc = SBC_OK; }
682
+ }
683
+ free(dc);
684
+ return rc;
685
+ }
686
+ static int sbc_ecdsa_verify(int bits, int curve, const sbc_u8* point, size_t pl, const sbc_u8* sig, size_t sl, const sbc_u8* m, size_t ml, int* ok) {
687
+ *ok = 0;
688
+ size_t fs = sbc_curve_size(curve);
689
+ if (!fs || pl != 1 + 2 * fs || point[0] != 4) return SBC_DATA;
690
+ sbc_u8 h[64];
691
+ if (!sbc_digest(bits, m, ml, h)) return SBC_NOTSUP;
692
+ if (sl != 2 * fs) return SBC_OK;
693
+ br_ec_public_key pk;
694
+ pk.curve = sbc_curve_br(curve); pk.q = (sbc_u8*)point; pk.qlen = pl;
695
+ if (br_ecdsa_vrfy_raw_get_default()(br_ec_get_default(), h, sbc_hlen(bits), &pk, sig, sl)) *ok = 1;
696
+ return SBC_OK;
697
+ }
698
+ /* A public point is valid when it is on the curve (the group is prime order, cofactor 1). */
699
+ static int sbc_ec_point_ok(int curve, const sbc_u8* point, size_t pl) {
700
+ size_t fs = sbc_curve_size(curve);
701
+ if (!fs || pl != 1 + 2 * fs || point[0] != 4) return 0;
702
+ sbc_u8 q[133];
703
+ memcpy(q, point, pl);
704
+ sbc_u8 one[1] = { 1 };
705
+ return br_ec_get_default()->mul(q, pl, one, 1, sbc_curve_br(curve)) != 0;
706
+ }
707
+ static int sbc_ec_keygen(int curve, sbc_buf* out) {
708
+ br_ec_private_key sk; br_ec_public_key pk;
709
+ sbc_u8 kb[BR_EC_KBUF_PRIV_MAX_SIZE], pb[BR_EC_KBUF_PUB_MAX_SIZE];
710
+ const br_ec_impl* impl = br_ec_get_default();
711
+ if (!br_ec_keygen(&sbc_prng, impl, &sk, kb, sbc_curve_br(curve))) return SBC_OPERATION;
712
+ if (!br_ec_compute_pub(impl, &pk, pb, &sk)) return SBC_OPERATION;
713
+ size_t need = br_encode_ec_pkcs8_der(0, &sk, &pk);
714
+ sbc_u8* dst = (sbc_u8*)malloc(need);
715
+ if (!dst) return SBC_OPERATION;
716
+ br_encode_ec_pkcs8_der(dst, &sk, &pk);
717
+ sbc_put(out, dst, need);
718
+ free(dst);
719
+ memset(kb, 0, sizeof kb);
720
+ return SBC_OK;
721
+ }
722
+
723
+ /* ---- AES: GCM, CBC, CTR, KW ---------------------------------------------------------------- */
724
+
725
+ static int sbc_aes_key_ok(size_t kl) { return kl == 16 || kl == 24 || kl == 32; }
726
+
727
+ /* One block through AES, encrypt or decrypt (a one-block CBC with a zero IV is ECB). */
728
+ static void sbc_aes_block(int enc, const sbc_u8* key, size_t kl, const sbc_u8* in, sbc_u8* out) {
729
+ sbc_u8 iv[16] = {0};
730
+ memcpy(out, in, 16);
731
+ if (enc) { br_aes_ct_cbcenc_keys c; br_aes_ct_cbcenc_init(&c, key, kl); br_aes_ct_cbcenc_run(&c, iv, out, 16); }
732
+ else { br_aes_ct_cbcdec_keys c; br_aes_ct_cbcdec_init(&c, key, kl); br_aes_ct_cbcdec_run(&c, iv, out, 16); }
733
+ }
734
+
735
+ /* AES-GCM with a tag of tagbits (a multiple of 8, 32 to 128). Encryption appends the tag;
736
+ * decryption expects it at the end of the input and fails, with nothing output, on a bad tag. */
737
+ static int sbc_gcm(int enc, size_t tagbits, const sbc_u8* key, size_t kl, const sbc_u8* iv, size_t ivl,
738
+ const sbc_u8* in, size_t il, const sbc_u8* aad, size_t al, sbc_buf* out) {
739
+ size_t tl = tagbits / 8;
740
+ if (!sbc_aes_key_ok(kl) || ivl == 0 || tagbits < 32 || tagbits > 128 || tagbits % 8) return SBC_OPERATION;
741
+ size_t dl = il;
742
+ if (!enc) { if (il < tl) return SBC_OPERATION; dl = il - tl; }
743
+ sbc_u8* buf = (sbc_u8*)malloc(dl ? dl : 1);
744
+ if (!buf) return SBC_OPERATION;
745
+ memcpy(buf, in, dl);
746
+ br_aes_ct_ctr_keys bc; br_gcm_context gc;
747
+ br_aes_ct_ctr_init(&bc, key, kl);
748
+ br_gcm_init(&gc, &bc.vtable, br_ghash_ctmul);
749
+ br_gcm_reset(&gc, iv, ivl);
750
+ br_gcm_aad_inject(&gc, aad, al);
751
+ br_gcm_flip(&gc);
752
+ br_gcm_run(&gc, enc, buf, dl);
753
+ int rc = SBC_OK;
754
+ if (enc) {
755
+ sbc_u8 tag[16];
756
+ br_gcm_get_tag(&gc, tag);
757
+ sbc_put(out, buf, dl); sbc_put(out, tag, tl);
758
+ } else if (br_gcm_check_tag_trunc(&gc, in + dl, tl)) {
759
+ sbc_put(out, buf, dl);
760
+ } else rc = SBC_OPERATION;
761
+ memset(buf, 0, dl);
762
+ free(buf);
763
+ return rc;
764
+ }
765
+
766
+ /* AES-CBC with PKCS#7 padding. */
767
+ static int sbc_cbc(int enc, const sbc_u8* key, size_t kl, const sbc_u8* iv, size_t ivl, const sbc_u8* in, size_t il, sbc_buf* out) {
768
+ if (!sbc_aes_key_ok(kl) || ivl != 16) return SBC_OPERATION;
769
+ sbc_u8 v[16];
770
+ memcpy(v, iv, 16);
771
+ if (enc) {
772
+ size_t pad = 16 - il % 16, total = il + pad;
773
+ sbc_u8* buf = (sbc_u8*)malloc(total);
774
+ if (!buf) return SBC_OPERATION;
775
+ memcpy(buf, in, il); memset(buf + il, (int)pad, pad);
776
+ br_aes_ct_cbcenc_keys c;
777
+ br_aes_ct_cbcenc_init(&c, key, kl); br_aes_ct_cbcenc_run(&c, v, buf, total);
778
+ sbc_put(out, buf, total); free(buf);
779
+ return SBC_OK;
780
+ }
781
+ if (il == 0 || il % 16) return SBC_OPERATION;
782
+ sbc_u8* buf = (sbc_u8*)malloc(il);
783
+ if (!buf) return SBC_OPERATION;
784
+ memcpy(buf, in, il);
785
+ br_aes_ct_cbcdec_keys c;
786
+ br_aes_ct_cbcdec_init(&c, key, kl); br_aes_ct_cbcdec_run(&c, v, buf, il);
787
+ /* Padding check without branching on the pad byte value beyond its validity. */
788
+ sbc_u8 pad = buf[il - 1];
789
+ unsigned bad = (pad == 0) | (pad > 16);
790
+ for (size_t i = 0; i < 16 && i < il; i++) bad |= (i < pad) & (buf[il - 1 - i] != pad);
791
+ int rc = SBC_OPERATION;
792
+ if (!bad) { sbc_put(out, buf, il - pad); rc = SBC_OK; }
793
+ memset(buf, 0, il);
794
+ free(buf);
795
+ return rc;
796
+ }
797
+
798
+ /* Increment the low "bits" bits of a 16-byte big-endian counter, wrapping inside them. */
799
+ static void sbc_ctr_inc(sbc_u8* ctr, unsigned bits) {
800
+ unsigned carry = 1, left = bits;
801
+ for (int i = 15; i >= 0 && left > 0; i--) {
802
+ unsigned take = left >= 8 ? 8 : left;
803
+ unsigned m = (1u << take) - 1;
804
+ unsigned v = (ctr[i] & m) + carry;
805
+ carry = v > m;
806
+ ctr[i] = (sbc_u8)((ctr[i] & ~m) | (v & m));
807
+ left -= take;
808
+ }
809
+ }
810
+ /* AES-CTR as WebCrypto has it: the low "bits" bits of the counter block count, and the input
811
+ * may not be longer than that counter can number. */
812
+ static int sbc_ctr(const sbc_u8* key, size_t kl, const sbc_u8* ctr, size_t cl, unsigned bits, const sbc_u8* in, size_t il, sbc_buf* out) {
813
+ if (!sbc_aes_key_ok(kl) || cl != 16 || bits < 1 || bits > 128) return SBC_OPERATION;
814
+ size_t blocks = (il + 15) / 16;
815
+ if (bits < 64 && blocks > ((size_t)1 << bits)) return SBC_OPERATION;
816
+ sbc_u8 c[16], ks[16];
817
+ memcpy(c, ctr, 16);
818
+ br_aes_ct_cbcenc_keys ek;
819
+ br_aes_ct_cbcenc_init(&ek, key, kl);
820
+ for (size_t off = 0; off < il; off += 16) {
821
+ sbc_u8 iv[16] = {0};
822
+ memcpy(ks, c, 16);
823
+ br_aes_ct_cbcenc_run(&ek, iv, ks, 16);
824
+ size_t n = il - off < 16 ? il - off : 16;
825
+ for (size_t j = 0; j < n; j++) sbc_put1(out, (sbc_u8)(in[off + j] ^ ks[j]));
826
+ sbc_ctr_inc(c, bits);
827
+ }
828
+ return SBC_OK;
829
+ }
830
+
831
+ /* AES Key Wrap, RFC 3394. */
832
+ static int sbc_kw(int wrap, const sbc_u8* key, size_t kl, const sbc_u8* in, size_t il, sbc_buf* out) {
833
+ if (!sbc_aes_key_ok(kl)) return SBC_OPERATION;
834
+ size_t n;
835
+ sbc_u8 a[8], b[16];
836
+ if (wrap) {
837
+ if (il < 16 || il % 8) return SBC_OPERATION;
838
+ n = il / 8;
839
+ sbc_u8* r = (sbc_u8*)malloc(il);
840
+ if (!r) return SBC_OPERATION;
841
+ memcpy(r, in, il);
842
+ memset(a, 0xa6, 8);
843
+ for (unsigned j = 0; j < 6; j++)
844
+ for (size_t i = 0; i < n; i++) {
845
+ memcpy(b, a, 8); memcpy(b + 8, r + 8 * i, 8);
846
+ sbc_aes_block(1, key, kl, b, b);
847
+ uint64_t t = (uint64_t)n * j + i + 1;
848
+ memcpy(a, b, 8);
849
+ for (int k = 0; k < 8; k++) a[7 - k] ^= (sbc_u8)(t >> (8 * k));
850
+ memcpy(r + 8 * i, b + 8, 8);
851
+ }
852
+ sbc_put(out, a, 8); sbc_put(out, r, il);
853
+ free(r);
854
+ return SBC_OK;
855
+ }
856
+ if (il < 24 || il % 8) return SBC_OPERATION;
857
+ n = il / 8 - 1;
858
+ sbc_u8* r = (sbc_u8*)malloc(il);
859
+ if (!r) return SBC_OPERATION;
860
+ memcpy(a, in, 8); memcpy(r, in + 8, il - 8);
861
+ for (int j = 5; j >= 0; j--)
862
+ for (size_t i = n; i >= 1; i--) {
863
+ uint64_t t = (uint64_t)n * (unsigned)j + i;
864
+ memcpy(b, a, 8);
865
+ for (int k = 0; k < 8; k++) b[7 - k] ^= (sbc_u8)(t >> (8 * k));
866
+ memcpy(b + 8, r + 8 * (i - 1), 8);
867
+ sbc_aes_block(0, key, kl, b, b);
868
+ memcpy(a, b, 8); memcpy(r + 8 * (i - 1), b + 8, 8);
869
+ }
870
+ sbc_u8 iv[8]; memset(iv, 0xa6, 8);
871
+ int rc = SBC_OPERATION;
872
+ if (sbc_ct_eq(a, iv, 8)) { sbc_put(out, r, il - 8); rc = SBC_OK; }
873
+ free(r);
874
+ return rc;
875
+ }
876
+
877
+ /* ---- key agreement ------------------------------------------------------------------------- */
878
+
879
+ static int sbc_ecdh(int curve, const sbc_u8* pkcs8, size_t kl, const sbc_u8* peer, size_t pl, sbc_buf* out) {
880
+ br_skey_decoder_context* dc; const br_ec_private_key* sk;
881
+ int rc = sbc_ec_load_private(pkcs8, kl, &dc, &sk);
882
+ if (rc != SBC_OK) return rc;
883
+ size_t fs = sbc_curve_size(curve);
884
+ rc = SBC_OPERATION;
885
+ if (sk->curve == sbc_curve_br(curve) && fs && pl == 1 + 2 * fs && peer[0] == 4) {
886
+ sbc_u8 pt[133];
887
+ memcpy(pt, peer, pl);
888
+ if (br_ec_get_default()->mul(pt, pl, sk->x, sk->xlen, sk->curve)) {
889
+ size_t xl; size_t xo = br_ec_get_default()->xoff(sk->curve, &xl);
890
+ sbc_put(out, pt + xo, xl); rc = SBC_OK;
891
+ }
892
+ }
893
+ free(dc);
894
+ return rc;
895
+ }
896
+ static int sbc_x25519(const sbc_u8* seed, size_t sl, const sbc_u8* peer, size_t pl, sbc_buf* out) {
897
+ if (sl != 32 || pl != 32) return SBC_OPERATION;
898
+ sbc_u8 shared[32], zero[32] = {0};
899
+ crypto_x25519(shared, seed, peer);
900
+ /* A low-order peer point gives all zeros: WebCrypto calls that an OperationError. */
901
+ if (sbc_ct_eq(shared, zero, 32)) return SBC_OPERATION;
902
+ sbc_put(out, shared, 32);
903
+ return SBC_OK;
904
+ }
905
+
906
+ /* ---- RSA-OAEP ------------------------------------------------------------------------------ */
907
+
908
+ static int sbc_oaep(int enc, int bits, const sbc_u8* key, size_t kl, const sbc_u8* label, size_t ll, const sbc_u8* in, size_t il, sbc_buf* out) {
909
+ const br_hash_class* hc = sbc_hash(bits);
910
+ if (!hc) return SBC_NOTSUP;
911
+ if (enc) {
912
+ br_rsa_public_key pk;
913
+ if (!sbc_load_rsa_public(key, kl, &pk)) return SBC_DATA;
914
+ sbc_u8 buf[512];
915
+ if (pk.nlen > sizeof buf) return SBC_OPERATION;
916
+ size_t n = br_rsa_oaep_encrypt_get_default()(&sbc_prng, hc, label, ll, &pk, buf, sizeof buf, in, il);
917
+ if (!n) return SBC_OPERATION;
918
+ sbc_put(out, buf, n);
919
+ return SBC_OK;
920
+ }
921
+ sbc_rsa_fields kf; br_rsa_private_key sk;
922
+ if (!sbc_rsa_parse_pkcs8(key, kl, &kf)) return SBC_DATA;
923
+ sbc_rsa_bear_key(&kf, &sk);
924
+ sbc_u8 buf[512];
925
+ size_t k = (sk.n_bitlen + 7) / 8;
926
+ if (il != k || k > sizeof buf) return SBC_OPERATION;
927
+ memcpy(buf, in, il);
928
+ size_t len = il;
929
+ if (!br_rsa_oaep_decrypt_get_default()(hc, label, ll, &sk, buf, &len)) return SBC_OPERATION;
930
+ sbc_put(out, buf, len);
931
+ memset(buf, 0, sizeof buf);
932
+ return SBC_OK;
933
+ }
934
+
935
+ /* ---- the dispatcher ------------------------------------------------------------------------ */
936
+
937
+ #define SBC_OP_RSA_PKCS1_SIGN 1
938
+ #define SBC_OP_RSA_PKCS1_VERIFY 2
939
+ #define SBC_OP_RSA_PSS_SIGN 3
940
+ #define SBC_OP_RSA_PSS_VERIFY 4
941
+ #define SBC_OP_ECDSA_SIGN 5
942
+ #define SBC_OP_ECDSA_VERIFY 6
943
+ #define SBC_OP_ED_SIGN 7
944
+ #define SBC_OP_ED_VERIFY 8
945
+ #define SBC_OP_PBKDF2 9
946
+ #define SBC_OP_HKDF 10
947
+ #define SBC_OP_AES_GCM_ENC 11
948
+ #define SBC_OP_AES_GCM_DEC 12
949
+ #define SBC_OP_AES_CBC_ENC 13
950
+ #define SBC_OP_AES_CBC_DEC 14
951
+ #define SBC_OP_AES_CTR 15
952
+ #define SBC_OP_AES_KW_WRAP 16
953
+ #define SBC_OP_AES_KW_UNWRAP 17
954
+ #define SBC_OP_ECDH 18
955
+ #define SBC_OP_X25519 19
956
+ #define SBC_OP_DECODE_SPKI 20
957
+ #define SBC_OP_DECODE_PKCS8 21
958
+ #define SBC_OP_ENCODE_SPKI 22
959
+ #define SBC_OP_ENCODE_PKCS8 23
960
+ #define SBC_OP_OAEP_ENC 24
961
+ #define SBC_OP_OAEP_DEC 25
962
+ #define SBC_OP_RSA_KEYGEN 26
963
+ #define SBC_OP_EC_KEYGEN 27
964
+ #define SBC_OP_ED_KEYGEN 28
965
+ #define SBC_OP_ED_PUB 29
966
+ #define SBC_OP_EC_POINT_OK 30
967
+ #define SBC_OP_X25519_PUB 31
968
+
969
+ /* a: parameters ("n,n,..."), b, c, d: byte strings. On success *out is malloc'd (may be NULL for
970
+ * an empty result). Returns SBC_OK or an error code. */
971
+ static int sbc_op(int op, const sbc_u8* a, size_t al, const sbc_u8* b, size_t bl, const sbc_u8* c, size_t cl,
972
+ const sbc_u8* d, size_t dl, sbc_u8** result, size_t* resultlen) {
973
+ sbc_buf out = {0};
974
+ int rc = SBC_NOTSUP, ok = 0;
975
+ long p0 = sbc_param(a, al, 0), p1 = sbc_param(a, al, 1), p2 = sbc_param(a, al, 2);
976
+ switch (op) {
977
+ case SBC_OP_RSA_PKCS1_SIGN: rc = sbc_hash((int)p0) ? sbc_rsa_pkcs1_sign((int)p0, b, bl, c, cl, &out) : SBC_NOTSUP; break;
978
+ case SBC_OP_RSA_PKCS1_VERIFY:
979
+ rc = sbc_hash((int)p0) ? sbc_rsa_pkcs1_verify((int)p0, b, bl, c, cl, d, dl, &ok) : SBC_NOTSUP;
980
+ if (rc == SBC_OK) sbc_put1(&out, (sbc_u8)ok);
981
+ break;
982
+ case SBC_OP_RSA_PSS_SIGN: rc = sbc_hash((int)p0) && p1 >= 0 ? sbc_rsa_pss_sign((int)p0, (size_t)p1, b, bl, c, cl, &out) : SBC_NOTSUP; break;
983
+ case SBC_OP_RSA_PSS_VERIFY:
984
+ rc = sbc_hash((int)p0) && p1 >= 0 ? sbc_rsa_pss_verify((int)p0, (size_t)p1, b, bl, c, cl, d, dl, &ok) : SBC_NOTSUP;
985
+ if (rc == SBC_OK) sbc_put1(&out, (sbc_u8)ok);
986
+ break;
987
+ case SBC_OP_ECDSA_SIGN: rc = sbc_hash((int)p0) ? sbc_ecdsa_sign((int)p0, b, bl, c, cl, &out) : SBC_NOTSUP; break;
988
+ case SBC_OP_ECDSA_VERIFY:
989
+ rc = sbc_hash((int)p0) ? sbc_ecdsa_verify((int)p0, (int)p1, b, bl, c, cl, d, dl, &ok) : SBC_NOTSUP;
990
+ if (rc == SBC_OK) sbc_put1(&out, (sbc_u8)ok);
991
+ break;
992
+ case SBC_OP_ED_SIGN: {
993
+ if (bl != 32) { rc = SBC_DATA; break; }
994
+ sbc_u8 sk[64], pk[32], seed[32], sig[64];
995
+ memcpy(seed, b, 32);
996
+ crypto_ed25519_key_pair(sk, pk, seed);
997
+ crypto_ed25519_sign(sig, sk, c, cl);
998
+ sbc_put(&out, sig, 64); rc = SBC_OK;
999
+ break;
1000
+ }
1001
+ case SBC_OP_ED_VERIFY:
1002
+ if (bl != 32) { rc = SBC_DATA; break; }
1003
+ sbc_put1(&out, (sbc_u8)(cl == 64 && crypto_ed25519_check(c, b, d, dl) == 0));
1004
+ rc = SBC_OK;
1005
+ break;
1006
+ case SBC_OP_PBKDF2:
1007
+ if (!sbc_hash((int)p0) || p1 < 1 || p2 < 0 || p2 > 1048576) break;
1008
+ { sbc_u8* o = (sbc_u8*)malloc(p2 ? (size_t)p2 : 1);
1009
+ if (!o) { rc = SBC_OPERATION; break; }
1010
+ sbc_pbkdf2((int)p0, b, bl, c, cl, (uint32_t)p1, o, (size_t)p2);
1011
+ sbc_put(&out, o, (size_t)p2); free(o); rc = SBC_OK; }
1012
+ break;
1013
+ case SBC_OP_HKDF:
1014
+ if (!sbc_hash((int)p0) || p1 < 0 || p1 > 255 * (long)sbc_hlen((int)p0)) break;
1015
+ { sbc_u8* o = (sbc_u8*)malloc(p1 ? (size_t)p1 : 1);
1016
+ if (!o) { rc = SBC_OPERATION; break; }
1017
+ sbc_hkdf((int)p0, b, bl, c, cl, d, dl, o, (size_t)p1);
1018
+ sbc_put(&out, o, (size_t)p1); free(o); rc = SBC_OK; }
1019
+ break;
1020
+ case SBC_OP_AES_GCM_ENC:
1021
+ case SBC_OP_AES_GCM_DEC: {
1022
+ /* d is framed: data, additional data. */
1023
+ const sbc_u8 *dp = d, *data, *aad; size_t dleft = dl, datal, aadl;
1024
+ if (p0 < 0 || !sbc_next(&dp, &dleft, &data, &datal) || !sbc_next(&dp, &dleft, &aad, &aadl)) break;
1025
+ rc = sbc_gcm(op == SBC_OP_AES_GCM_ENC, (size_t)p0, b, bl, c, cl, data, datal, aad, aadl, &out);
1026
+ break;
1027
+ }
1028
+ case SBC_OP_AES_CBC_ENC: rc = sbc_cbc(1, b, bl, c, cl, d, dl, &out); break;
1029
+ case SBC_OP_AES_CBC_DEC: rc = sbc_cbc(0, b, bl, c, cl, d, dl, &out); break;
1030
+ case SBC_OP_AES_CTR: rc = p0 > 0 ? sbc_ctr(b, bl, c, cl, (unsigned)p0, d, dl, &out) : SBC_NOTSUP; break;
1031
+ case SBC_OP_AES_KW_WRAP: rc = sbc_kw(1, b, bl, d, dl, &out); break;
1032
+ case SBC_OP_AES_KW_UNWRAP: rc = sbc_kw(0, b, bl, d, dl, &out); break;
1033
+ case SBC_OP_ECDH: rc = sbc_ecdh((int)p0, b, bl, c, cl, &out); break;
1034
+ case SBC_OP_X25519: rc = sbc_x25519(b, bl, c, cl, &out); break;
1035
+ case SBC_OP_X25519_PUB: {
1036
+ if (bl != 32) { rc = SBC_DATA; break; }
1037
+ sbc_u8 pk[32];
1038
+ crypto_x25519_public_key(pk, b);
1039
+ sbc_put(&out, pk, 32); rc = SBC_OK;
1040
+ break;
1041
+ }
1042
+ case SBC_OP_OAEP_ENC: rc = sbc_oaep(1, (int)p0, b, bl, c, cl, d, dl, &out); break;
1043
+ case SBC_OP_OAEP_DEC: rc = sbc_oaep(0, (int)p0, b, bl, c, cl, d, dl, &out); break;
1044
+ case SBC_OP_DECODE_SPKI: rc = sbc_decode(0, b, bl, &out); break;
1045
+ case SBC_OP_DECODE_PKCS8: rc = sbc_decode(1, b, bl, &out); break;
1046
+ case SBC_OP_ENCODE_SPKI: rc = sbc_encode(0, (int)p0, (int)p1, b, bl, &out); break;
1047
+ case SBC_OP_ENCODE_PKCS8: rc = sbc_encode(1, (int)p0, (int)p1, b, bl, &out); break;
1048
+ case SBC_OP_RSA_KEYGEN: rc = p0 > 0 && p1 > 0 ? sbc_rsa_keygen((unsigned)p0, (uint32_t)p1, &out) : SBC_NOTSUP; break;
1049
+ case SBC_OP_EC_KEYGEN: rc = sbc_curve_br((int)p0) ? sbc_ec_keygen((int)p0, &out) : SBC_NOTSUP; break;
1050
+ case SBC_OP_ED_KEYGEN: {
1051
+ sbc_u8 seed[32];
1052
+ if (!sbc_rand(seed, 32)) { rc = SBC_OPERATION; break; }
1053
+ sbc_put(&out, seed, 32); memset(seed, 0, 32); rc = SBC_OK;
1054
+ break;
1055
+ }
1056
+ case SBC_OP_ED_PUB: {
1057
+ if (bl != 32) { rc = SBC_DATA; break; }
1058
+ sbc_u8 sk[64], pk[32], seed[32];
1059
+ memcpy(seed, b, 32);
1060
+ crypto_ed25519_key_pair(sk, pk, seed);
1061
+ sbc_put(&out, pk, 32); rc = SBC_OK;
1062
+ break;
1063
+ }
1064
+ case SBC_OP_EC_POINT_OK:
1065
+ sbc_put1(&out, (sbc_u8)sbc_ec_point_ok((int)p0, b, bl)); rc = SBC_OK;
1066
+ break;
1067
+ }
1068
+ if (out.bad) rc = SBC_OPERATION;
1069
+ if (rc != SBC_OK) { free(out.p); out.p = 0; out.n = 0; }
1070
+ *result = out.p; *resultlen = out.n;
1071
+ return rc;
1072
+ }