File Coverage

inc/matrixssl-3-9-3-open/crypto/pubkey/ecc.c
Criterion Covered Total %
statement 537 1217 44.1
branch 365 950 38.4
condition n/a
subroutine n/a
pod n/a
total 902 2167 41.6


line stmt bran cond sub pod time code
1             /**
2             * @file ecc.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * Implements ECC over Z/pZ for curve y^2 = x^3 + ax + b.
6             */
7             /*
8             * Copyright (c) 2013-2017 INSIDE Secure Corporation
9             * Copyright (c) PeerSec Networks, 2002-2011
10             * All Rights Reserved
11             *
12             * The latest version of this code is available at http://www.matrixssl.org
13             *
14             * This software is open source; you can redistribute it and/or modify
15             * it under the terms of the GNU General Public License as published by
16             * the Free Software Foundation; either version 2 of the License, or
17             * (at your option) any later version.
18             *
19             * This General Public License does NOT permit incorporating this software
20             * into proprietary programs. If you are unable to comply with the GPL, a
21             * commercial license for this software may be purchased from INSIDE at
22             * http://www.insidesecure.com/
23             *
24             * This program is distributed in WITHOUT ANY WARRANTY; without even the
25             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26             * See the GNU General Public License for more details.
27             *
28             * You should have received a copy of the GNU General Public License
29             * along with this program; if not, write to the Free Software
30             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31             * http://www.gnu.org/copyleft/gpl.html
32             */
33             /******************************************************************************/
34              
35             #include "../cryptoImpl.h"
36              
37             #ifdef USE_MATRIX_ECC
38              
39             /******************************************************************************/
40              
41             # define ECC_BUF_SIZE 256
42              
43             static psEccPoint_t *eccNewPoint(psPool_t *pool, short size);
44             static void eccFreePoint(psEccPoint_t *p);
45              
46             static int32_t eccMulmod(psPool_t *pool, const pstm_int *k, const psEccPoint_t *G,
47             psEccPoint_t *R, pstm_int *modulus, uint8_t map, pstm_int *tmp_int);
48             static int32_t eccProjectiveAddPoint(psPool_t *pool, const psEccPoint_t *P,
49             const psEccPoint_t *Q, psEccPoint_t *R, const pstm_int *modulus,
50             const pstm_digit *mp, pstm_int *tmp_int);
51             static int32_t eccProjectiveDblPoint(psPool_t *pool, const psEccPoint_t *P,
52             psEccPoint_t *R, const pstm_int *modulus, const pstm_digit *mp,
53             const pstm_int *A);
54             static int32_t eccMap(psPool_t *pool, psEccPoint_t *P, const pstm_int *modulus,
55             const pstm_digit *mp);
56              
57             /*
58             This array holds the ecc curve settings.
59              
60             The recommended elliptic curve domain parameters over p have been given
61             nicknames to enable them to be easily identified. The nicknames were
62             chosen as follows. Each name begins with sec to denote ‘Standards for
63             Efficient Cryptography’, followed by a p to denote parameters over p,
64             followed by a number denoting the length in bits of the field size p,
65             followed by a k to denote parameters associated with a Koblitz curve or an
66             r to denote verifiably random parameters, followed by a sequence number.
67              
68             typedef struct {
69             uint8_t size; // The size of the curve in octets
70             psCurve16_t curveId; // IANA named curve id for TLS use
71             uint8_t isOptimized; // 1 if optimized with field parameter A=-3
72             uint32_t OIDsum; // Internal Matrix OID
73             //Domain parameters
74             const char *name; // name of curve
75             const char *prime; // prime defining the field the curve is in (hex)
76             const char *A; // The fields A param (hex)
77             const char *B; // The fields B param (hex)
78             const char *order; // The order of the curve (hex)
79             const char *Gx; // The x co-ordinate of the base point on the curve (hex)
80             const char *Gy; // The y co-ordinate of the base point on the curve (hex)
81             } psEccCurve_t;
82             */
83             const static psEccCurve_t eccCurves[] = {
84             # ifdef USE_SECP521R1
85             {
86             66,
87             IANA_SECP521R1,
88             1, /* isOptimized */
89             211, /* 43.129.4.0.35 */
90             "secp521r1",
91             "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
92             "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
93             "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
94             "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
95             "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
96             "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
97             },
98             # endif
99             # ifdef USE_BRAIN512R1
100             {
101             64, /* size in octets */
102             IANA_BRAIN512R1,
103             0, /* isOptimized */
104             110, /* 1.3.36.3.3.2.8.1.1.13 */
105             "brainpoolP512r1",
106             "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
107             "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
108             "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
109             "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
110             "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
111             "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
112             },
113             # endif
114             # ifdef USE_SECP384R1
115             {
116             48,
117             IANA_SECP384R1,
118             1, /* isOptimized */
119             210, /* 43.129.4.0.34 */
120             "secp384r1",
121             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
122             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
123             "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
124             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
125             "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
126             "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
127             },
128             # endif
129             # ifdef USE_BRAIN384R1
130             {
131             48, /* size in octets */
132             IANA_BRAIN384R1,
133             0, /* isOptimized */
134             108, /* 1.3.36.3.3.2.8.1.1.11 */
135             "brainpoolP384r1",
136             "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
137             "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
138             "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
139             "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
140             "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
141             "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
142             },
143             # endif
144             # ifdef USE_SECP256R1
145             {
146             32,
147             IANA_SECP256R1,
148             1, /* isOptimized */
149             526, /* 42.134.72.206.61.3.1.7 */
150             "secp256r1",
151             "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
152             "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
153             "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
154             "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
155             "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
156             "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
157             },
158             # endif
159             # ifdef USE_BRAIN256R1
160             {
161             32, /* size in octets */
162             IANA_BRAIN256R1,
163             0, /* isOptimized */
164             104, /* 1.3.36.3.3.2.8.1.1.7 */
165             "brainpoolP256r1",
166             "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
167             "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
168             "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
169             "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
170             "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
171             "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
172             },
173             # endif
174             # ifdef USE_SECP224R1
175             {
176             28,
177             IANA_SECP224R1,
178             1, /* isOptimized */
179             209, /* 43.129.4.0.33 */
180             "secp224r1",
181             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
182             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
183             "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
184             "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
185             "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
186             "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
187             },
188             # endif
189             # ifdef USE_BRAIN224R1
190             {
191             28, /* size in octets */
192             IANA_BRAIN224R1,
193             0, /* isOptimized */
194             102, /* 1.3.36.3.3.2.8.1.1.5 */
195             "brainpoolP224r1",
196             "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
197             "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
198             "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
199             "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
200             "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
201             "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD"
202             },
203             # endif
204             # ifdef USE_SECP192R1
205             {
206             24, /* size in octets */
207             IANA_SECP192R1, /* IANA named curve ID */
208             1, /* isOptimized */
209             520, /* 42.134.72.206.61.3.1.1 */
210             "secp192r1",
211             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */
212             "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A = -3 */
213             "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B */
214             "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* order */
215             "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx */
216             "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", /* Gy */
217             },
218             # endif
219             {
220             0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
221             }
222             };
223              
224             /*****************************************************************************/
225             /**
226             Initialize an ecc key, and assign the curve, if provided.
227             @param[in] pool Memory pool
228             @param[out] key Pointer to allocated ECC key to initialize
229             @param[in] curve Curve to assign, or NULL.
230             @return < 0 on failure, 0 on success.
231             @note To allocate and initialize a key, use psEccNewKey().
232             */
233 6668           int32_t psEccInitKey(psPool_t *pool, psEccKey_t *key, const psEccCurve_t *curve)
234             {
235 6668 50         if (!key)
236             {
237 0           return PS_MEM_FAIL;
238             }
239 6668           memset(key, 0x0, sizeof(psEccKey_t));
240 6668           key->pool = pool;
241 6668           key->pubkey.pool = pool;
242 6668           key->curve = curve; /* Curve can be NULL */
243             /* key->type will be set by one of the key generate/import/read functions */
244 6668           return PS_SUCCESS;
245             }
246              
247             /**
248             Clear an ECC key.
249             @param[out] key Pointer to allocated ECC key to clear.
250             @note Caller is responsible for freeing memory associated with key structure,
251             if appropriate.
252             */
253 4477           void psEccClearKey(psEccKey_t *key)
254             {
255 4477 50         psAssert(key);
256             /* Clear private k separately, since it may not be present */
257 4477           pstm_clear(&key->k);
258 4477           pstm_clear_multi(
259             &key->pubkey.x,
260             &key->pubkey.y,
261             &key->pubkey.z,
262             NULL, NULL, NULL, NULL, NULL);
263 4477           key->curve = NULL;
264 4477           key->pool = NULL;
265 4477           key->pubkey.pool = NULL;
266 4477           key->type = 0;
267 4477           }
268              
269             /**
270             Allocate memory for an ECC key and initialize it.
271             @param[in] pool Memory pool
272             @param[out] key Pointer to unallocated ECC key to initialize. Will
273             point to allocated and initialized key on successful return.
274             @param[in] curve Curve to assign, or NULL.
275             @return < 0 on failure, 0 on success.
276             */
277 4316           int32_t psEccNewKey(psPool_t *pool, psEccKey_t **key, const psEccCurve_t *curve)
278             {
279             psEccKey_t *k;
280             int32_t rc;
281              
282 4316 50         if ((k = psMalloc(pool, sizeof(psEccKey_t))) == NULL)
283             {
284 0           return PS_MEM_FAIL;
285             }
286 4316           k->type = 0;
287 4316 50         if ((rc = psEccInitKey(pool, k, curve)) < 0)
288             {
289 0           psFree(k, pool);
290 0           return rc;
291             }
292 4316           *key = k;
293 4316           return PS_SUCCESS;
294             }
295              
296             /* 'to' digits will be allocated here */
297 2203           int32 psEccCopyKey(psEccKey_t *to, psEccKey_t *from)
298             {
299             int32 rc;
300              
301 2203 50         if (to->pool == NULL)
302             {
303 2203           to->pool = from->pool;
304 2203           to->pubkey.pool = from->pubkey.pool;
305             }
306             else
307             {
308 0           to->pubkey.pool = to->pool;
309             }
310 2203           to->curve = from->curve;
311 2203           to->type = from->type;
312              
313             /* pubkey */
314 2203 50         if ((rc = pstm_init_copy(to->pool, &to->pubkey.x, &from->pubkey.x, 0))
315             != PSTM_OKAY)
316             {
317 0           goto error;
318             }
319 2203 50         if ((rc = pstm_init_copy(to->pool, &to->pubkey.y, &from->pubkey.y, 0))
320             != PSTM_OKAY)
321             {
322 0           goto error;
323             }
324 2203 50         if ((rc = pstm_init_copy(to->pool, &to->pubkey.z, &from->pubkey.z, 0))
325             != PSTM_OKAY)
326             {
327 0           goto error;
328             }
329              
330             /* privkey */
331 2203 50         if (to->type == PS_PRIVKEY)
332             {
333 2203 50         if ((rc = pstm_init_copy(to->pool, &to->k, &from->k, 0))
334             != PSTM_OKAY)
335             {
336 0           goto error;
337             }
338             }
339              
340             error:
341 2203 50         if (rc < 0)
342             {
343 0           psEccClearKey(from);
344             }
345 2203           return rc;
346             }
347              
348             /**
349             Free memory for an ECC key and clear it.
350             @param[out] key Pointer to dynamically allocated ECC key to free. Pointer
351             will be cleared, freed and set to NULL on return.
352             */
353 4316           void psEccDeleteKey(psEccKey_t **key)
354             {
355 4316           psEccKey_t *k = *key;
356              
357 4316           psEccClearKey(k);
358 4316           psFree(k, NULL);
359 4316           *key = NULL;
360 4316           }
361              
362             /**
363             ECC key size in bytes.
364             @return Public key size in bytes if key->type is public, otherwise private size.
365             @note ECC public keys are twice as many bytes as private keys.
366             */
367 105           uint8_t psEccSize(const psEccKey_t *key)
368             {
369 105 50         if (key && key->curve)
    50          
370             {
371 105           return key->curve->size * 2;
372             }
373 0           return 0;
374             }
375              
376             /*****************************************************************************/
377             /*
378             Called from the cert parse. The initial bytes in this stream are
379             technically the EcpkParameters from the ECDSA pub key OBJECT IDENTIFIER
380             that name the curve. The asnGetAlgorithmIdentifier call right before
381             this just stripped out the OID
382             */
383 105           int32_t getEcPubKey(psPool_t *pool, const unsigned char **pp, psSize_t len,
384             psEccKey_t *pubKey, unsigned char sha1KeyHash[SHA1_HASH_SIZE])
385             {
386             # ifdef USE_SHA1
387             psDigestContext_t dc;
388             # endif
389             const psEccCurve_t *eccCurve;
390 105           const unsigned char *p = *pp, *end;
391             int32_t oid;
392             psSize_t arcLen;
393             uint8_t ignore_bits;
394              
395 105           end = p + len;
396 105 50         if (len < 1 ||
    50          
397 105 50         *(p++) != ASN_OID ||
398 210 50         getAsnLength(&p, (uint16_t) (end - p), &arcLen) < 0 ||
399 105           (uint16_t) (end - p) < arcLen)
400             {
401              
402             psTraceCrypto("Only namedCurve types are supported in EC certs\n");
403 0           return PS_PARSE_FAIL;
404             }
405             /*
406             NamedCurve OIDs
407              
408             ansi-x9-62 OBJECT IDENTIFER ::= {
409             iso(1) member-body(2) us(840) 10045
410             }
411              
412             secp192r1 OBJECT IDENTIFIER ::= { ansi-x9-62 curves(3) prime(1) 1 }
413             2a8648ce3d030101 -> sum = 520
414              
415             secp256r1 OBJECT IDENTIFIER ::= { ansi-x9-62 curves(3) prime(1) 7 }
416             2a8648ce3d030107 -> sum = 526
417             */
418             /* Note arcLen could be zero here */
419 105           oid = 0;
420 660 100         while (arcLen > 0)
421             {
422 555           oid += *p++;
423 555           arcLen--;
424             }
425             /* Match the sum against our list of curves to make sure we got it */
426 105 50         if (getEccParamByOid(oid, &eccCurve) < 0)
427             {
428             psTraceCrypto("Cert named curve not found in eccCurve list\n");
429 0           return PS_UNSUPPORTED_FAIL;
430             }
431              
432 210 50         if ((uint16_t) (end - p) < 1 || (*(p++) != ASN_BIT_STRING) ||
433 210 50         getAsnLength(&p, len - 1, &arcLen) < 0 ||
434 105 50         (uint16_t) (end - p) < arcLen ||
435 105           arcLen < 1)
436             {
437              
438             psTraceCrypto("Unexpected ECC pubkey format\n");
439 0           return PS_PARSE_FAIL;
440             }
441 105           ignore_bits = *p++;
442 105           arcLen--;
443             if (ignore_bits != 0)
444             {
445             psTraceCrypto("Unexpected ECC ignore_bits\n");
446             }
447              
448             # ifdef USE_SHA1
449             /* A public key hash is used in PKI tools (OCSP, Trusted CA indication).
450             Standard form - SHA-1 hash of the value of the BIT STRING
451             subjectPublicKey [excluding the tag, length, and number of unused
452             bits] */
453 105           psSha1PreInit(&dc.sha1);
454 105           psSha1Init(&dc.sha1);
455 105           psSha1Update(&dc.sha1, p, arcLen);
456 105           psSha1Final(&dc.sha1, sha1KeyHash);
457             # endif
458              
459             /* Note arcLen could again be zero here */
460 105 50         if (psEccX963ImportKey(pool, p, arcLen, pubKey, eccCurve) < 0)
461             {
462             psTraceCrypto("Unable to parse ECC pubkey from cert\n");
463 0           return PS_PARSE_FAIL;
464             }
465 105           p += arcLen;
466              
467 105           *pp = p;
468              
469 105           return PS_SUCCESS;
470             }
471              
472             /**
473             Initialize an ECC key and generate a public/private keypair for the given
474             curve.
475             @param pool Memory pool
476             @param[out] key Uninitialized ECC key. This API will call psEccInitKey() on this key.
477             @param[in] curve ECC named curve to use for key.
478             @param[in] usrData User data pointer to pass to hardware implementations that use it.
479             @return < 0 on failure.
480             */
481 29           int32_t psEccGenKey(psPool_t *pool, psEccKey_t *key, const psEccCurve_t *curve,
482             void *usrData)
483             {
484             int32_t err;
485             psSize_t keysize, slen;
486             psEccPoint_t *base;
487 29           pstm_int *A = NULL;
488             pstm_int prime, order, rand;
489             unsigned char *buf;
490              
491 29 50         if (!key || !curve)
    50          
492             {
493             psTraceCrypto("Only named curves supported in psEccGenKey\n");
494 0           return PS_UNSUPPORTED_FAIL;
495             }
496              
497 29           psEccInitKey(pool, key, curve);
498 29           keysize = curve->size; /* Note, curve is non-null */
499 29           slen = keysize * 2;
500              
501             /* allocate ram */
502 29           base = NULL;
503 29           buf = psMalloc(pool, ECC_MAXSIZE);
504 29 50         if (buf == NULL)
505             {
506 0           psError("Memory allocation error in psEccGenKey\n");
507 0           err = PS_MEM_FAIL;
508 0           goto ERR_KEY;
509             }
510              
511             /* Make sure random number is less than "order" */
512 29 50         if (pstm_init_for_read_unsigned_bin(pool, &order, keysize) < 0)
513             {
514 0           err = PS_MEM_FAIL;
515 0           goto ERR_BUF;
516             }
517              
518 29 50         if ((err = pstm_read_radix(pool, &order, key->curve->order, slen, 16))
519             != PS_SUCCESS)
520             {
521 0           pstm_clear(&order);
522 0           goto ERR_BUF;
523             }
524              
525             /* make up random string */
526             RETRY_RAND:
527 3344 50         if (psGetPrngLocked(buf, keysize, usrData) != keysize)
528             {
529 0           err = PS_PLATFORM_FAIL;
530 0           pstm_clear(&order);
531 0           goto ERR_BUF;
532             }
533              
534 3344 50         if (pstm_init_for_read_unsigned_bin(pool, &rand, keysize) < 0)
535             {
536 0           err = PS_MEM_FAIL;
537 0           pstm_clear(&order);
538 0           goto ERR_BUF;
539             }
540              
541 3344 50         if ((err = pstm_read_unsigned_bin(&rand, buf, keysize)) != PS_SUCCESS)
542             {
543 0           pstm_clear(&order);
544 0           pstm_clear(&rand);
545 0           goto ERR_BUF;
546             }
547              
548             /* Make sure random number is less than "order" */
549 3344 100         if (pstm_cmp(&rand, &order) == PSTM_GT)
550             {
551 3315           pstm_clear(&rand);
552 3315           goto RETRY_RAND;
553             }
554 29           pstm_clear(&rand);
555 29           pstm_clear(&order);
556              
557 29 50         if (key->curve->isOptimized == 0)
558             {
559 0 0         if ((A = psMalloc(pool, sizeof(pstm_int))) == NULL)
560             {
561 0           err = PS_MEM_FAIL;
562 0           goto ERR_BUF;
563             }
564 0 0         if (pstm_init_for_read_unsigned_bin(pool, A, keysize) < 0)
565             {
566 0           err = PS_MEM_FAIL;
567 0           psFree(A, pool);
568 0           goto ERR_BUF;
569             }
570 0 0         if ((err = pstm_read_radix(pool, A, key->curve->A, slen, 16))
571             != PS_SUCCESS)
572             {
573 0           goto ERR_A;
574             }
575             }
576              
577 29 50         if (pstm_init_for_read_unsigned_bin(pool, &prime, keysize) < 0)
578             {
579 0           err = PS_MEM_FAIL;
580 0           goto ERR_A;
581             }
582              
583 29           base = eccNewPoint(pool, prime.alloc);
584 29 50         if (base == NULL)
585             {
586 0           err = PS_MEM_FAIL;
587 0           goto ERR_PRIME;
588             }
589              
590             /* read in the specs for this key */
591 29 50         if ((err = pstm_read_radix(pool, &prime, key->curve->prime, slen, 16))
592             != PS_SUCCESS)
593             {
594 0           goto ERR_BASE;
595             }
596 29 50         if ((err = pstm_read_radix(pool, &base->x, key->curve->Gx, slen, 16))
597             != PS_SUCCESS)
598             {
599 0           goto ERR_BASE;
600             }
601 29 50         if ((err = pstm_read_radix(pool, &base->y, key->curve->Gy, slen, 16))
602             != PS_SUCCESS)
603             {
604 0           goto ERR_BASE;
605             }
606 29           pstm_set(&base->z, 1);
607              
608 29 50         if (pstm_init_for_read_unsigned_bin(pool, &key->k, keysize) < 0)
609             {
610 0           err = PS_MEM_FAIL;
611 0           goto ERR_BASE;
612             }
613 29 50         if ((err = pstm_read_unsigned_bin(&key->k, buf, keysize))
614             != PS_SUCCESS)
615             {
616 0           goto ERR_BASE;
617             }
618              
619             /* make the public key */
620 29 50         if (pstm_init_size(pool, &key->pubkey.x, (key->k.used * 2) + 1) < 0)
621             {
622 0           err = PS_MEM_FAIL;
623 0           goto ERR_BASE;
624             }
625 29 50         if (pstm_init_size(pool, &key->pubkey.y, (key->k.used * 2) + 1) < 0)
626             {
627 0           err = PS_MEM_FAIL;
628 0           goto ERR_BASE;
629             }
630 29 50         if (pstm_init_size(pool, &key->pubkey.z, (key->k.used * 2) + 1) < 0)
631             {
632 0           err = PS_MEM_FAIL;
633 0           goto ERR_BASE;
634             }
635 29 50         if ((err = eccMulmod(pool, &key->k, base, &key->pubkey, &prime, 1, A)) !=
636             PS_SUCCESS)
637             {
638 0           goto ERR_BASE;
639             }
640              
641 29           key->type = PS_PRIVKEY;
642              
643             /* frees for success */
644 29           eccFreePoint(base);
645 29           pstm_clear(&prime);
646 29 50         if (A)
647             {
648 0           pstm_clear(A);
649 0           psFree(A, pool);
650             }
651 29           psFree(buf, pool);
652 29           return PS_SUCCESS;
653              
654             ERR_BASE:
655 0           eccFreePoint(base);
656             ERR_PRIME:
657 0           pstm_clear(&prime);
658             ERR_A:
659 0 0         if (A)
660             {
661 0           pstm_clear(A);
662 0           psFree(A, pool);
663             }
664             ERR_BUF:
665 0           psFree(buf, pool);
666             ERR_KEY:
667 0           psEccClearKey(key);
668 29           return err;
669             }
670              
671             # if defined(MATRIX_USE_FILE_SYSTEM) && defined(USE_PRIVATE_KEY_PARSING)
672             /******************************************************************************/
673             /*
674             ECPrivateKey{CURVES:IOSet} ::= SEQUENCE {
675             version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
676             privateKey OCTET STRING,
677             parameters [0] Parameters{{IOSet}} OPTIONAL,
678             publicKey [1] BIT STRING OPTIONAL
679             }
680              
681             */
682 0           int32_t psEccParsePrivFile(psPool_t *pool, const char *fileName,
683             const char *password, psEccKey_t *key)
684             {
685             unsigned char *DERout;
686             int32_t rc;
687             psSize_t DERlen;
688              
689             # ifdef USE_PKCS8
690             psPubKey_t pubkey;
691             # endif
692              
693 0 0         if ((rc = psPkcs1DecodePrivFile(pool, fileName, password, &DERout, &DERlen)) < 0)
694             {
695 0           return rc;
696             }
697              
698 0 0         if ((rc = psEccParsePrivKey(pool, DERout, DERlen, key, NULL)) < 0)
699             {
700             # ifdef USE_PKCS8
701             /* This logic works for processing PKCS#8 files becuase the above file
702             and bin decodes will always leave the unprocessed buffer intact and
703             the password protection is done in the internal ASN.1 encoding */
704 0 0         if ((rc = psPkcs8ParsePrivBin(pool, DERout, DERlen, (char *) password,
705             &pubkey)) < 0)
706             {
707 0           psFree(DERout, pool);
708 0           return rc;
709             }
710 0           rc = psEccCopyKey(key, &pubkey.key.ecc);
711 0           psClearPubKey(&pubkey);
712             # else
713             psFree(DERout, pool);
714             return rc;
715             # endif
716             }
717 0           psFree(DERout, pool);
718 0           return PS_SUCCESS;
719             }
720             # endif /* MATRIX_USE_FILE_SYSTEM && USE_PRIVATE_KEY_PARSING */
721              
722 0           int32_t psEccParsePrivKey(psPool_t *pool,
723             const unsigned char *keyBuf, psSize_t keyBufLen,
724             psEccKey_t *key, const psEccCurve_t *curve)
725             {
726             const psEccCurve_t *eccCurve;
727             const unsigned char *buf, *end;
728             uint8_t ignore_bits;
729             uint32_t oid;
730             int32_t asnInt;
731             psSize_t len;
732             size_t privkey_len;
733              
734 0           buf = keyBuf;
735 0           end = buf + keyBufLen;
736              
737 0 0         if (getAsnSequence(&buf, (uint16_t) (end - buf), &len) < 0)
738             {
739             psTraceCrypto("ECDSA subject signature parse failure 1\n");
740 0           return PS_FAILURE;
741             }
742 0 0         if (getAsnInteger(&buf, (uint16_t) (end - buf), &asnInt) < 0 ||
    0          
743 0           asnInt != 1)
744             {
745             psTraceCrypto("Expecting private key flag\n");
746 0           return PS_FAILURE;
747             }
748             /* Initial curve check */
749 0           if ((*buf++ != ASN_OCTET_STRING) ||
750 0 0         getAsnLength(&buf, (uint16_t) (end - buf), &len) < 0 ||
751 0 0         (uint16_t) (end - buf) < len ||
752 0           len < (MIN_ECC_BITS / 8))
753             {
754             psTraceCrypto("Expecting private key octet string\n");
755 0           return PS_FAILURE;
756             }
757 0           privkey_len = len;
758              
759 0           psEccInitKey(pool, key, curve);
760 0 0         if (pstm_init_for_read_unsigned_bin(pool, &key->k, len) != PS_SUCCESS)
761             {
762 0           goto L_FAIL;
763             }
764             /* Key material */
765 0 0         if (pstm_read_unsigned_bin(&key->k, buf, len) != PS_SUCCESS)
766             {
767             psTraceCrypto("Unable to read private key octet string\n");
768 0           goto L_FAIL;
769             }
770 0           key->type = PS_PRIVKEY;
771 0           buf += len;
772              
773 0 0         if (*buf == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
774             {
775              
776             /* optional parameters are present */
777 0           buf++;
778 0 0         if (getAsnLength(&buf, (uint16_t) (end - buf), &len) < 0 ||
    0          
779 0 0         (uint16_t) (end - buf) < len ||
780 0           len < 1)
781             {
782              
783             psTraceCrypto("Bad private key format\n");
784             goto L_FAIL;
785             }
786 0           if (*(buf++) != ASN_OID ||
787 0 0         getAsnLength(&buf, (uint16_t) (end - buf), &len) < 0 ||
788 0           (uint16_t) (end - buf) < len)
789             {
790              
791             psTraceCrypto("Only namedCurves are supported in EC keys\n");
792             goto L_FAIL;
793             }
794             /* Note len can be 0 here */
795 0           oid = 0;
796 0 0         while (len > 0)
797             {
798 0           oid += *buf++;
799 0           len--;
800             }
801 0 0         if (getEccParamByOid(oid, &eccCurve) < 0)
802             {
803             psTraceCrypto("Cert named curve not found in eccCurve list\n");
804 0           goto L_FAIL;
805             }
806 0 0         if (curve != NULL && curve != eccCurve)
    0          
807             {
808             psTraceCrypto("PrivKey named curve doesn't match desired\n");
809 0           goto L_FAIL;
810             }
811 0           key->curve = eccCurve;
812              
813             }
814 0 0         else if (curve != NULL)
815             {
816 0           key->curve = curve;
817             }
818             else
819             {
820             psTraceCrypto("No curve found in EC private key\n");
821 0           goto L_FAIL;
822             }
823              
824 0 0         if (*buf == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1))
825             {
826             /* optional public key is present */
827 0           buf++;
828 0 0         if (getAsnLength(&buf, (uint16_t) (end - buf), &len) < 0 ||
    0          
829 0 0         (uint16_t) (end - buf) < len ||
830 0           len < 1)
831             {
832              
833             psTraceCrypto("Bad private key format\n");
834             goto L_FAIL;
835             }
836 0           if (*(buf++) != ASN_BIT_STRING ||
837 0 0         getAsnLength(&buf, (uint16_t) (end - buf), &len) < 0 ||
838 0 0         (uint16_t) (end - buf) < len ||
839 0           len < 1)
840             {
841              
842             goto L_FAIL;
843             }
844 0           ignore_bits = *buf++;
845 0           len--;
846 0 0         if (ignore_bits != 0)
847             {
848             psTraceCrypto("Unexpected ECC pubkey format\n");
849 0           goto L_FAIL;
850             }
851              
852             /* Note len can be 0 here */
853 0 0         if (psEccX963ImportKey(pool, buf, len, key, key->curve) < 0)
854             {
855             psTraceCrypto("Unable to parse ECC pubkey from cert\n");
856 0           goto L_FAIL;
857             }
858 0           buf += len;
859             }
860             /* Try to parse 'implicitly' encoded optional public key with no
861             DER header, i.e. assume that all the remaining bytes are public
862             key bytes. This is not valid ASN.1, but sometimes appears in
863             practice and parsing it is a requirement for some users. */
864 0 0         if (buf < end &&
    0          
865 0 0         *buf == ANSI_UNCOMPRESSED && /* Uncompressed is the only format we support. */
866 0           ((end - (buf + 1)) == privkey_len * 2)) /* Pubkey must be 2x privkey size. */
867             {
868 0 0         if (psEccX963ImportKey(pool, buf, (end - buf), key, key->curve) < 0)
869             {
870             psTraceCrypto("Unable to parse ECC pubkey from cert\n");
871 0           goto L_FAIL;
872             }
873 0           buf += (end - buf);
874             }
875              
876             /* Should be at the end */
877 0 0         if (end != buf)
878             {
879             /* If this stream came from an encrypted file, there could be
880             padding bytes on the end */
881 0           len = (uint16_t) (end - buf);
882 0 0         while (buf < end)
883             {
884 0 0         if (*buf != len)
885             {
886             psTraceCrypto("Problem at end of private key parse\n");
887 0           goto L_FAIL;
888             }
889 0           buf++;
890             }
891             }
892 0           return PS_SUCCESS;
893              
894             L_FAIL:
895 0           psEccClearKey(key);
896 0           return PS_FAIL;
897             }
898              
899 2233           int32_t getEccParamById(psCurve16_t curveId, const psEccCurve_t **curve)
900             {
901 2233           int i = 0;
902              
903             /* A curveId of zero is asking for a default curver */
904 2233 50         if (curveId == 0)
905             {
906 0           *curve = &eccCurves[0];
907 0           return 0;
908             }
909              
910 2233           *curve = NULL;
911 2295 50         while (eccCurves[i].size > 0)
912             {
913 2295 100         if (curveId == eccCurves[i].curveId)
914             {
915 2233           *curve = &eccCurves[i];
916 2233           return 0;
917             }
918 62           i++;
919             }
920 0           return PS_FAIL;
921             }
922              
923 105           int32_t getEccParamByOid(uint32_t oid, const psEccCurve_t **curve)
924             {
925 105           int i = 0;
926              
927 105           *curve = NULL;
928 220 50         while (eccCurves[i].size > 0)
929             {
930 220 100         if (oid == eccCurves[i].OIDsum)
931             {
932 105           *curve = &eccCurves[i];
933 105           return 0;
934             }
935 115           i++;
936             }
937 0           return PS_FAIL;
938             }
939              
940 0           int32_t getEccParamByName(const char *curveName,
941             const psEccCurve_t **curve)
942             {
943 0           int i = 0;
944              
945 0           *curve = NULL;
946 0 0         while (eccCurves[i].size > 0)
947             {
948 0 0         if (strcmp(curveName, eccCurves[i].name) == 0)
949             {
950 0           *curve = &eccCurves[i];
951 0           return 0;
952             }
953 0           i++;
954             }
955 0           return PS_FAIL;
956             }
957              
958             /**
959             Return a list of all supported curves.
960             This method will put the largest bit strength first in the list, because
961             of their order in the eccCurves[] array.
962             */
963 11156           void psGetEccCurveIdList(unsigned char *curveList, uint8_t *len)
964             {
965 11156           psSize_t listLen = 0, i = 0;
966              
967 66936 100         while (eccCurves[i].size > 0)
968             {
969 55780 50         if (listLen < (*len - 2))
970             {
971 55780           curveList[listLen++] = (eccCurves[i].curveId & 0xFF00) >> 8;
972 55780           curveList[listLen++] = eccCurves[i].curveId & 0xFF;
973             }
974 55780           i++;
975             }
976 11156           *len = listLen;
977 11156           }
978              
979             /**
980             User set list of curves they want to support.
981             This method will put the largest bit strength first in the list.
982             @param[in] curves Flags indicating which curves to use.
983             */
984 6           void userSuppliedEccList(unsigned char *curveList, uint8_t *len, uint32_t curves)
985             {
986             const psEccCurve_t *curve;
987 6           uint8_t listLen = 0;
988              
989 6 50         if (curves & IS_SECP521R1)
990             {
991 6 50         if (getEccParamById(IANA_SECP521R1, &curve) == 0)
992             {
993 6 50         if (listLen < (*len - 2))
994             {
995 6           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
996 6           curveList[listLen++] = curve->curveId & 0xFF;
997             }
998             }
999             }
1000 6 50         if (curves & IS_BRAIN512R1)
1001             {
1002 0 0         if (getEccParamById(IANA_BRAIN512R1, &curve) == 0)
1003             {
1004 0 0         if (listLen < (*len - 2))
1005             {
1006 0           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1007 0           curveList[listLen++] = curve->curveId & 0xFF;
1008             }
1009             }
1010             }
1011 6 50         if (curves & IS_SECP384R1)
1012             {
1013 6 50         if (getEccParamById(IANA_SECP384R1, &curve) == 0)
1014             {
1015 6 50         if (listLen < (*len - 2))
1016             {
1017 6           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1018 6           curveList[listLen++] = curve->curveId & 0xFF;
1019             }
1020             }
1021             }
1022 6 50         if (curves & IS_BRAIN384R1)
1023             {
1024 0 0         if (getEccParamById(IANA_BRAIN384R1, &curve) == 0)
1025             {
1026 0 0         if (listLen < (*len - 2))
1027             {
1028 0           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1029 0           curveList[listLen++] = curve->curveId & 0xFF;
1030             }
1031             }
1032             }
1033 6 50         if (curves & IS_SECP256R1)
1034             {
1035 6 50         if (getEccParamById(IANA_SECP256R1, &curve) == 0)
1036             {
1037 6 50         if (listLen < (*len - 2))
1038             {
1039 6           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1040 6           curveList[listLen++] = curve->curveId & 0xFF;
1041             }
1042             }
1043             }
1044 6 50         if (curves & IS_BRAIN256R1)
1045             {
1046 0 0         if (getEccParamById(IANA_BRAIN256R1, &curve) == 0)
1047             {
1048 0 0         if (listLen < (*len - 2))
1049             {
1050 0           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1051 0           curveList[listLen++] = curve->curveId & 0xFF;
1052             }
1053             }
1054             }
1055 6 50         if (curves & IS_SECP224R1)
1056             {
1057 6 50         if (getEccParamById(IANA_SECP224R1, &curve) == 0)
1058             {
1059 6 50         if (listLen < (*len - 2))
1060             {
1061 6           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1062 6           curveList[listLen++] = curve->curveId & 0xFF;
1063             }
1064             }
1065             }
1066 6 50         if (curves & IS_BRAIN224R1)
1067             {
1068 0 0         if (getEccParamById(IANA_BRAIN224R1, &curve) == 0)
1069             {
1070 0 0         if (listLen < (*len - 2))
1071             {
1072 0           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1073 0           curveList[listLen++] = curve->curveId & 0xFF;
1074             }
1075             }
1076             }
1077 6 50         if (curves & IS_SECP192R1)
1078             {
1079 6 50         if (getEccParamById(IANA_SECP192R1, &curve) == 0)
1080             {
1081 6 50         if (listLen < (*len - 2))
1082             {
1083 6           curveList[listLen++] = (curve->curveId & 0xFF00) >> 8;
1084 6           curveList[listLen++] = curve->curveId & 0xFF;
1085             }
1086             }
1087             }
1088              
1089 6           *len = listLen;
1090 6           }
1091              
1092 22314           uint32_t compiledInEcFlags(void)
1093             {
1094 22314           uint32_t ecFlags = 0;
1095              
1096             # ifdef USE_SECP192R1
1097 22314           ecFlags |= IS_SECP192R1;
1098             # endif
1099             # ifdef USE_SECP224R1
1100 22314           ecFlags |= IS_SECP224R1;
1101             # endif
1102             # ifdef USE_SECP256R1
1103 22314           ecFlags |= IS_SECP256R1;
1104             # endif
1105             # ifdef USE_SECP384R1
1106 22314           ecFlags |= IS_SECP384R1;
1107             # endif
1108             # ifdef USE_SECP521R1
1109 22314           ecFlags |= IS_SECP521R1;
1110             # endif
1111             # ifdef USE_BRAIN224R1
1112             ecFlags |= IS_BRAIN224R1;
1113             # endif
1114             # ifdef USE_BRAIN256R1
1115             ecFlags |= IS_BRAIN256R1;
1116             # endif
1117             # ifdef USE_BRAIN384R1
1118             ecFlags |= IS_BRAIN384R1;
1119             # endif
1120             # ifdef USE_BRAIN512R1
1121             ecFlags |= IS_BRAIN512R1;
1122             # endif
1123              
1124 22314           return ecFlags;
1125             }
1126              
1127             /******************************************************************************/
1128              
1129 2142           static uint8_t get_digit_count(const pstm_int *a)
1130             {
1131 2142           return a->used;
1132             }
1133              
1134 19268           static pstm_digit get_digit(const pstm_int *a, uint8_t n)
1135             {
1136 19268 50         return (n >= a->used) ? (pstm_digit) 0 : a->dp[n];
1137             }
1138              
1139             /******************************************************************************/
1140             /**
1141             Perform a point multiplication
1142             @param[in] pool Memory pool
1143             @param[in] k The scalar to multiply by
1144             @param[in] G The base point
1145             @param[out] R Destination for kG
1146             @param modulus The modulus of the field the ECC curve is in
1147             @param map Boolean whether to map back to affine or not (1==map)
1148             @param[in,out] tmp_int Temporary scratch big integer (memory optimization)
1149             @return PS_SUCCESS on success, < 0 on error
1150             */
1151             /* size of sliding window, don't change this! */
1152             # define ECC_MULMOD_WINSIZE 4
1153              
1154 2142           static int32_t eccMulmod(psPool_t *pool, const pstm_int *k, const psEccPoint_t *G,
1155             psEccPoint_t *R, pstm_int *modulus, uint8_t map, pstm_int *tmp_int)
1156             {
1157             psEccPoint_t *tG, *M[8]; /* @note large on stack */
1158             int32 i, j, err;
1159             pstm_int mu;
1160             pstm_digit mp;
1161             unsigned long buf;
1162             int32 first, bitbuf, bitcpy, bitcnt, mode, digidx;
1163              
1164             /* init montgomery reduction */
1165 2142 50         if ((err = pstm_montgomery_setup(modulus, &mp)) != PS_SUCCESS)
1166             {
1167 0           return err;
1168             }
1169 2142 50         if ((err = pstm_init_size(pool, &mu, modulus->alloc)) != PS_SUCCESS)
1170             {
1171 0           return err;
1172             }
1173 2142 50         if ((err = pstm_montgomery_calc_normalization(&mu, modulus)) != PS_SUCCESS)
1174             {
1175 0           pstm_clear(&mu);
1176 0           return err;
1177             }
1178              
1179             /* alloc ram for window temps */
1180 19278 100         for (i = 0; i < 8; i++)
1181             {
1182 17136           M[i] = eccNewPoint(pool, (G->x.used * 2) + 1);
1183 17136 50         if (M[i] == NULL)
1184             {
1185 0 0         for (j = 0; j < i; j++)
1186             {
1187 0           eccFreePoint(M[j]);
1188             }
1189 0           pstm_clear(&mu);
1190 0           return PS_MEM_FAIL;
1191             }
1192             }
1193              
1194             /* make a copy of G incase R==G */
1195 2142           tG = eccNewPoint(pool, G->x.alloc);
1196 2142 50         if (tG == NULL)
1197             {
1198 0           err = PS_MEM_FAIL;
1199 0           goto done;
1200             }
1201              
1202             /* tG = G and convert to montgomery */
1203 2142 50         if (pstm_cmp_d(&mu, 1) == PSTM_EQ)
1204             {
1205 0 0         if ((err = pstm_copy(&G->x, &tG->x)) != PS_SUCCESS)
1206             {
1207 0           goto done;
1208             }
1209 0 0         if ((err = pstm_copy(&G->y, &tG->y)) != PS_SUCCESS)
1210             {
1211 0           goto done;
1212             }
1213 0 0         if ((err = pstm_copy(&G->z, &tG->z)) != PS_SUCCESS)
1214             {
1215 0           goto done;
1216             }
1217             }
1218             else
1219             {
1220 2142 50         if ((err = pstm_mulmod(pool, &G->x, &mu, modulus, &tG->x)) != PS_SUCCESS)
1221             {
1222 0           goto done;
1223             }
1224 2142 50         if ((err = pstm_mulmod(pool, &G->y, &mu, modulus, &tG->y)) != PS_SUCCESS)
1225             {
1226 0           goto done;
1227             }
1228 2142 50         if ((err = pstm_mulmod(pool, &G->z, &mu, modulus, &tG->z)) != PS_SUCCESS)
1229             {
1230 0           goto done;
1231             }
1232             }
1233 2142           pstm_clear(&mu);
1234              
1235             /* calc the M tab, which holds kG for k==8..15 */
1236             /* M[0] == 8G */
1237 2142 50         if ((err = eccProjectiveDblPoint(pool, tG, M[0], modulus, &mp, tmp_int)) != PS_SUCCESS)
1238             {
1239 0           goto done;
1240             }
1241 2142 50         if ((err = eccProjectiveDblPoint(pool, M[0], M[0], modulus, &mp, tmp_int)) !=
1242             PS_SUCCESS)
1243             {
1244 0           goto done;
1245             }
1246 2142 50         if ((err = eccProjectiveDblPoint(pool, M[0], M[0], modulus, &mp, tmp_int)) !=
1247             PS_SUCCESS)
1248             {
1249 0           goto done;
1250             }
1251              
1252             /* now find (8+k)G for k=1..7 */
1253 17136 100         for (j = 9; j < 16; j++)
1254             {
1255 14994 50         if ((err = eccProjectiveAddPoint(pool, M[j - 9], tG, M[j - 8], modulus,
1256             &mp, tmp_int)) != PS_SUCCESS)
1257             {
1258 0           goto done;
1259             }
1260             }
1261              
1262             /* setup sliding window */
1263 2142           mode = 0;
1264 2142           bitcnt = 1;
1265 2142           buf = 0;
1266 2142           digidx = get_digit_count(k) - 1;
1267 2142           bitcpy = bitbuf = 0;
1268 2142           first = 1;
1269              
1270             /* perform ops */
1271             for (;; )
1272             {
1273             /* grab next digit as required */
1274 1235294 100         if (--bitcnt == 0)
1275             {
1276 21410 100         if (digidx == -1)
1277             {
1278 2142           break;
1279             }
1280 19268           buf = get_digit(k, digidx);
1281 19268           bitcnt = DIGIT_BIT;
1282 19268           --digidx;
1283             }
1284              
1285             /* grab the next msb from the ltiplicand */
1286 1233152           i = (buf >> (DIGIT_BIT - 1)) & 1;
1287 1233152           buf <<= 1;
1288              
1289             /* skip leading zero bits */
1290 1233152 100         if (mode == 0 && i == 0)
    100          
1291             {
1292 120803           continue;
1293             }
1294              
1295             /* if the bit is zero and mode == 1 then we double */
1296 1112349 100         if (mode == 1 && i == 0)
    100          
1297             {
1298 188616 50         if ((err = eccProjectiveDblPoint(pool, R, R, modulus, &mp, tmp_int)) !=
1299             PS_SUCCESS)
1300             {
1301 0           goto done;
1302             }
1303 188616           continue;
1304             }
1305              
1306             /* else we add it to the window */
1307 923733           bitbuf |= (i << (ECC_MULMOD_WINSIZE - ++bitcpy));
1308 923733           mode = 2;
1309              
1310 923733 100         if (bitcpy == ECC_MULMOD_WINSIZE)
1311             {
1312             /* if this is the first window we do a simple copy */
1313 229961 100         if (first == 1)
1314             {
1315             /* R = kG [k = first window] */
1316 2142 50         if ((err = pstm_copy(&M[bitbuf - 8]->x, &R->x)) != PS_SUCCESS)
1317             {
1318 0           goto done;
1319             }
1320 2142 50         if ((err = pstm_copy(&M[bitbuf - 8]->y, &R->y)) != PS_SUCCESS)
1321             {
1322 0           goto done;
1323             }
1324 2142 50         if ((err = pstm_copy(&M[bitbuf - 8]->z, &R->z)) != PS_SUCCESS)
1325             {
1326 0           goto done;
1327             }
1328 2142           first = 0;
1329             }
1330             else
1331             {
1332             /* normal window */
1333             /* ok window is filled so double as required and add */
1334             /* double first */
1335 1139095 100         for (j = 0; j < ECC_MULMOD_WINSIZE; j++)
1336             {
1337 911276 50         if ((err = eccProjectiveDblPoint(pool, R, R, modulus, &mp, tmp_int))
1338             != PS_SUCCESS)
1339             {
1340 0           goto done;
1341             }
1342             }
1343              
1344             /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
1345 227819 50         if ((err = eccProjectiveAddPoint(pool, R, M[bitbuf - 8], R,
1346             modulus, &mp, tmp_int)) != PS_SUCCESS)
1347             {
1348 0           goto done;
1349             }
1350             }
1351             /* empty window and reset */
1352 229961           bitcpy = bitbuf = 0;
1353 229961           mode = 1;
1354             }
1355 1233152           }
1356              
1357             /* if bits remain then double/add */
1358 2142 100         if (mode == 2 && bitcpy > 0)
    50          
1359             {
1360             /* double then add */
1361 5878 100         for (j = 0; j < bitcpy; j++)
1362             {
1363             /* only double if we have had at least one add first */
1364 3889 50         if (first == 0)
1365             {
1366 3889 50         if ((err = eccProjectiveDblPoint(pool, R, R, modulus, &mp, tmp_int)) !=
1367             PS_SUCCESS)
1368             {
1369 0           goto done;
1370             }
1371             }
1372              
1373 3889           bitbuf <<= 1;
1374 3889 100         if ((bitbuf & (1 << ECC_MULMOD_WINSIZE)) != 0)
1375             {
1376 2921 50         if (first == 1)
1377             {
1378             /* first add, so copy */
1379 0 0         if ((err = pstm_copy(&tG->x, &R->x)) != PS_SUCCESS)
1380             {
1381 0           goto done;
1382             }
1383 0 0         if ((err = pstm_copy(&tG->y, &R->y)) != PS_SUCCESS)
1384             {
1385 0           goto done;
1386             }
1387 0 0         if ((err = pstm_copy(&tG->z, &R->z)) != PS_SUCCESS)
1388             {
1389 0           goto done;
1390             }
1391 0           first = 0;
1392             }
1393             else
1394             {
1395             /* then add */
1396 2921 50         if ((err = eccProjectiveAddPoint(pool, R, tG, R, modulus,
1397             &mp, tmp_int)) != PS_SUCCESS)
1398             {
1399 0           goto done;
1400             }
1401             }
1402             }
1403             }
1404             }
1405              
1406             /* map R back from projective space */
1407 2142 50         if (map)
1408             {
1409 2142           err = eccMap(pool, R, modulus, &mp);
1410             }
1411             else
1412             {
1413 0           err = PS_SUCCESS;
1414             }
1415             done:
1416              
1417 2142           pstm_clear(&mu);
1418 2142           eccFreePoint(tG);
1419 19278 100         for (i = 0; i < 8; i++)
1420             {
1421 17136           eccFreePoint(M[i]);
1422             }
1423 2142           return err;
1424             }
1425              
1426 2218           static int32 eccTestPoint(psPool_t *pool, psEccPoint_t *P, pstm_int *prime,
1427             pstm_int *b)
1428             {
1429             pstm_int t1, t2;
1430             uint32 paDlen;
1431             pstm_digit *paD;
1432             int32 err;
1433              
1434 2218 50         if ((err = pstm_init(pool, &t1)) < 0)
1435             {
1436 0           return err;
1437             }
1438 2218 50         if ((err = pstm_init(pool, &t2)) < 0)
1439             {
1440 0           pstm_clear(&t1);
1441 0           return err;
1442             }
1443             /* Pre-allocated digit. TODO: haven't fully explored max paDlen */
1444 2218           paDlen = (prime->used * 2 + 1) * sizeof(pstm_digit);
1445 2218 50         if ((paD = psMalloc(pool, paDlen)) == NULL)
1446             {
1447 0           pstm_clear(&t1);
1448 0           pstm_clear(&t2);
1449 0           return PS_MEM_FAIL;
1450             }
1451              
1452             /* compute y^2 */
1453 2218 50         if ((err = pstm_sqr_comba(pool, &P->y, &t1, paD, paDlen)) < 0)
1454             {
1455 0           goto error;
1456             }
1457              
1458             /* compute x^3 */
1459 2218 50         if ((err = pstm_sqr_comba(pool, &P->x, &t2, paD, paDlen)) < 0)
1460             {
1461 0           goto error;
1462             }
1463 2218 50         if ((err = pstm_mod(pool, &t2, prime, &t2)) < 0)
1464             {
1465 0           goto error;
1466             }
1467              
1468 2218 50         if ((err = pstm_mul_comba(pool, &P->x, &t2, &t2, paD, paDlen)) < 0)
1469             {
1470 0           goto error;
1471             }
1472              
1473             /* compute y^2 - x^3 */
1474 2218 50         if ((err = pstm_sub(&t1, &t2, &t1)) < 0)
1475             {
1476 0           goto error;
1477             }
1478              
1479             /* compute y^2 - x^3 + 3x */
1480 2218 50         if ((err = pstm_add(&t1, &P->x, &t1)) < 0)
1481             {
1482 0           goto error;
1483             }
1484 2218 50         if ((err = pstm_add(&t1, &P->x, &t1)) < 0)
1485             {
1486 0           goto error;
1487             }
1488 2218 50         if ((err = pstm_add(&t1, &P->x, &t1)) < 0)
1489             {
1490 0           goto error;
1491             }
1492 2218 50         if ((err = pstm_mod(pool, &t1, prime, &t1)) < 0)
1493             {
1494 0           goto error;
1495             }
1496 2218 50         while (pstm_cmp_d(&t1, 0) == PSTM_LT)
1497             {
1498 0 0         if ((err = pstm_add(&t1, prime, &t1)) < 0)
1499             {
1500 0           goto error;
1501             }
1502             }
1503 2218 50         while (pstm_cmp(&t1, prime) != PSTM_LT)
1504             {
1505 0 0         if ((err = pstm_sub(&t1, prime, &t1)) < 0)
1506             {
1507 0           goto error;
1508             }
1509             }
1510              
1511             /* compare to b */
1512 2218 50         if (pstm_cmp(&t1, b) != PSTM_EQ)
1513             {
1514             psTraceCrypto("Supplied EC public point not on curve\n");
1515 0           err = PS_LIMIT_FAIL;
1516             }
1517             else
1518             {
1519 2218           err = PS_SUCCESS;
1520             }
1521              
1522             error:
1523 2218           psFree(paD, pool);
1524 2218           pstm_clear(&t1);
1525 2218           pstm_clear(&t2);
1526 2218           return err;
1527             }
1528              
1529             /******************************************************************************/
1530             /**
1531             ANSI X9.62 or X9.63 (Section 4.3.7) uncompressed import.
1532             This function imports the public ECC key elements (the x, y and z values).
1533             If a private 'k' value is defined, the public elements are added to the
1534             key. Otherwise, only the public elements are loaded and the key
1535             marked public.
1536             The format of import is ASN.1, and is used both within certificate
1537             parsing and when parsing public keys passed on the wire in TLS.
1538              
1539             @param[in] pool Memory pool
1540             @param[in] in ECC key data in uncompressed form
1541             @param[in] inlen Length of destination and final output size
1542             @param[in, out] key Key to import. Private keys types will not be
1543             initialized, all others will.
1544             @param[in] curve Curve parameters, may be NULL
1545             @return PS_SUCCESS on success, < 0 on failure
1546             */
1547 2218           int32_t psEccX963ImportKey(psPool_t *pool,
1548             const unsigned char *in, psSize_t inlen,
1549             psEccKey_t *key, const psEccCurve_t *curve)
1550             {
1551             int32_t err;
1552             pstm_int prime, b;
1553              
1554             /* Must be odd and minimal size */
1555 2218 50         if (inlen < ((2 * (MIN_ECC_BITS / 8)) + 1) || (inlen & 1) == 0)
    50          
1556             {
1557 0           return PS_ARG_FAIL;
1558             }
1559              
1560             /* The key passed in may be a private key that is already initialized
1561             and the 'k' parameter set. */
1562 2218 50         if (key->type != PS_PRIVKEY)
1563             {
1564 2218 50         if (psEccInitKey(pool, key, curve) < 0)
1565             {
1566 0           return PS_MEM_FAIL;
1567             }
1568 2218           key->type = PS_PUBKEY;
1569             }
1570 2218 50         if (pstm_init_for_read_unsigned_bin(pool, &key->pubkey.x,
1571 2218           (inlen - 1) >> 1) < 0)
1572             {
1573 0           return PS_MEM_FAIL;
1574             }
1575 2218 50         if (pstm_init_for_read_unsigned_bin(pool, &key->pubkey.y,
1576 2218           (inlen - 1) >> 1) < 0)
1577             {
1578 0           pstm_clear(&key->pubkey.x);
1579 0           return PS_MEM_FAIL;
1580             }
1581 2218 50         if (pstm_init_size(pool, &key->pubkey.z, 1) < 0)
1582             {
1583 0           pstm_clear(&key->pubkey.x);
1584 0           pstm_clear(&key->pubkey.y);
1585 0           return PS_MEM_FAIL;
1586             }
1587              
1588 2218 50         switch (*in)
1589             {
1590             /* Standard, supported format */
1591             case ANSI_UNCOMPRESSED:
1592 2218           break;
1593             /* Unsupported formats */
1594             case ANSI_COMPRESSED0:
1595             case ANSI_COMPRESSED1:
1596             case ANSI_HYBRID0:
1597             case ANSI_HYBRID1:
1598             default:
1599             psTraceCrypto("ERROR: ECC compressed/hybrid formats unsupported\n");
1600 0           err = PS_UNSUPPORTED_FAIL;
1601 0           goto error;
1602             }
1603 2218 50         if ((err = pstm_read_unsigned_bin(&key->pubkey.x, (unsigned char *) in + 1,
1604 2218           (inlen - 1) >> 1)) != PS_SUCCESS)
1605             {
1606 0           goto error;
1607             }
1608 2218 50         if ((err = pstm_read_unsigned_bin(&key->pubkey.y,
1609 2218           (unsigned char *) in + 1 + ((inlen - 1) >> 1),
1610 2218           (inlen - 1) >> 1)) != PS_SUCCESS)
1611             {
1612 0           goto error;
1613             }
1614 2218           pstm_set(&key->pubkey.z, 1);
1615              
1616             /* Validate the point is on the curve */
1617 2218 50         if (curve != NULL && curve->isOptimized)
    50          
1618             {
1619 2218 50         if ((err = pstm_init_for_read_unsigned_bin(pool, &prime, curve->size)) < 0)
1620             {
1621 0           goto error;
1622             }
1623 2218 50         if ((err = pstm_init_for_read_unsigned_bin(pool, &b, curve->size)) < 0)
1624             {
1625 0           pstm_clear(&prime);
1626 0           goto error;
1627             }
1628 2218 50         if ((err = pstm_read_radix(pool, &prime, curve->prime,
1629 2218           curve->size * 2, 16)) < 0)
1630             {
1631 0           pstm_clear(&prime);
1632 0           pstm_clear(&b);
1633 0           goto error;
1634             }
1635              
1636 2218 50         if ((err = pstm_read_radix(pool, &b, curve->B, curve->size * 2, 16)) < 0)
1637             {
1638 0           pstm_clear(&prime);
1639 0           pstm_clear(&b);
1640 0           goto error;
1641             }
1642 2218 50         if ((err = eccTestPoint(pool, &key->pubkey, &prime, &b)) < 0)
1643             {
1644 0           pstm_clear(&prime);
1645 0           pstm_clear(&b);
1646 0           goto error;
1647             }
1648 2218           pstm_clear(&prime);
1649 2218           pstm_clear(&b);
1650             }
1651             else
1652             {
1653             psTraceCrypto("WARNING: ECC public key not validated\n");
1654             }
1655              
1656 2218           return PS_SUCCESS;
1657              
1658             error:
1659 0           psEccClearKey(key);
1660 2218           return err;
1661             }
1662              
1663             /******************************************************************************/
1664             /**
1665             ANSI X9.62 or X9.63 (Sec. 4.3.6) uncompressed export.
1666             @param[in] pool Memory pool
1667             @param[in] key Key to export
1668             @param[out] out [out] destination of export
1669             @param[in, out] outlen Length of destination and final output size
1670             @return PS_SUCCESS on success, < 0 on failure
1671             */
1672 2203           int32_t psEccX963ExportKey(psPool_t *pool, const psEccKey_t *key,
1673             unsigned char *out, psSize_t *outlen)
1674             {
1675             unsigned char buf[ECC_BUF_SIZE];
1676             unsigned long numlen;
1677             int32_t res;
1678              
1679 2203           numlen = key->curve->size;
1680 2203 50         if (*outlen < (1 + 2 * numlen))
1681             {
1682 0           *outlen = 1 + 2 * numlen;
1683 0           return PS_LIMIT_FAIL;
1684             }
1685              
1686 2203           out[0] = (unsigned char) ANSI_UNCOMPRESSED;
1687              
1688             /* pad and store x */
1689 2203           memset(buf, 0, sizeof(buf));
1690 2203 50         if ((res = pstm_to_unsigned_bin(pool, &key->pubkey.x, buf +
1691 2203           (numlen - pstm_unsigned_bin_size(&key->pubkey.x)))) != PSTM_OKAY)
1692             {
1693 0           return res;
1694             }
1695 2203           memcpy(out + 1, buf, numlen);
1696              
1697             /* pad and store y */
1698 2203           memset(buf, 0, sizeof(buf));
1699 2203 50         if ((res = pstm_to_unsigned_bin(pool, &key->pubkey.y, buf +
1700 2203           (numlen - pstm_unsigned_bin_size(&key->pubkey.y)))) != PSTM_OKAY)
1701             {
1702 0           return res;
1703             }
1704 2203           memcpy(out + 1 + numlen, buf, numlen);
1705              
1706 2203           *outlen = 1 + 2 * numlen;
1707 2203           return PS_SUCCESS;
1708             }
1709              
1710             /******************************************************************************/
1711             /**
1712             Create an ECC shared secret between two keys.
1713             @param[in] pool Memory pool
1714             @param[in] private_key The private ECC key
1715             @param[in] public_key The public key
1716             @param[out] out Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
1717             @param[in,out] outlen The max size and resulting size of the shared secret
1718             @param[in,out] usrData Opaque usrData for hardware offload.
1719             @return PS_SUCCESS if successful
1720             */
1721 2113           int32_t psEccGenSharedSecret(psPool_t *pool,
1722             const psEccKey_t *private_key, const psEccKey_t *public_key,
1723             unsigned char *out, psSize_t *outlen,
1724             void *usrData)
1725             {
1726             uint16_t x;
1727             psEccPoint_t *result;
1728 2113           pstm_int *A = NULL;
1729             pstm_int prime;
1730             int32_t err;
1731              
1732             /* type valid? */
1733 2113 50         if (private_key->type != PS_PRIVKEY)
1734             {
1735 0           return PS_ARG_FAIL;
1736             }
1737 2113 50         if (public_key->curve != NULL)
1738             {
1739 2113 50         if (private_key->curve != public_key->curve)
1740             {
1741 0           return PS_ARG_FAIL;
1742             }
1743             }
1744              
1745             /* make new point */
1746 2113           result = eccNewPoint(pool, (private_key->k.used * 2) + 1);
1747 2113 50         if (result == NULL)
1748             {
1749 0           return PS_MEM_FAIL;
1750             }
1751              
1752 2113 50         if (private_key->curve->isOptimized == 0)
1753             {
1754 0 0         if ((A = psMalloc(pool, sizeof(pstm_int))) == NULL)
1755             {
1756 0           eccFreePoint(result);
1757 0           return PS_MEM_FAIL;
1758             }
1759              
1760 0 0         if (pstm_init_for_read_unsigned_bin(pool, A, private_key->curve->size) < 0)
1761             {
1762 0           psFree(A, pool);
1763 0           eccFreePoint(result);
1764 0           return PS_MEM_FAIL;
1765             }
1766              
1767 0 0         if ((err = pstm_read_radix(pool, A, private_key->curve->A,
1768 0           private_key->curve->size * 2, 16))
1769             != PS_SUCCESS)
1770             {
1771 0           pstm_clear(A);
1772 0           psFree(A, pool);
1773 0           eccFreePoint(result);
1774 0           return err;
1775             }
1776             }
1777              
1778 2113 50         if ((err = pstm_init_for_read_unsigned_bin(pool, &prime,
1779 2113           private_key->curve->size)) != PS_SUCCESS)
1780             {
1781 0 0         if (A)
1782             {
1783 0           pstm_clear(A);
1784 0           psFree(A, pool);
1785             }
1786 0           eccFreePoint(result);
1787 0           return err;
1788             }
1789              
1790 2113 50         if ((err = pstm_read_radix(pool, &prime, private_key->curve->prime,
1791 2113           private_key->curve->size * 2, 16)) != PS_SUCCESS)
1792             {
1793 0           goto done;
1794             }
1795 2113 50         if ((err = eccMulmod(pool, &private_key->k, &public_key->pubkey, result,
1796             &prime, 1, A)) != PS_SUCCESS)
1797             {
1798 0           goto done;
1799             }
1800              
1801 2113           x = pstm_unsigned_bin_size(&prime);
1802 2113 50         if (*outlen < x)
1803             {
1804 0           *outlen = x;
1805 0           err = PS_LIMIT_FAIL;
1806 0           goto done;
1807             }
1808 2113           memset(out, 0, x);
1809 2113 50         if ((err = pstm_to_unsigned_bin(pool, &result->x,
1810 2113           out + (x - pstm_unsigned_bin_size(&result->x)))) != PS_SUCCESS)
1811             {
1812 0           goto done;
1813             }
1814              
1815 2113           err = PS_SUCCESS;
1816 2113           *outlen = x;
1817             done:
1818 2113 50         if (A)
1819             {
1820 0           pstm_clear(A);
1821 0           psFree(A, pool);
1822             }
1823 2113           pstm_clear(&prime);
1824 2113           eccFreePoint(result);
1825 2113           return err;
1826             }
1827              
1828             /******************************************************************************/
1829             /**
1830             Add two ECC points
1831             @param P The point to add
1832             @param Q The point to add
1833             @param[out] R The destination of the double
1834             @param modulus The modulus of the field the ECC curve is in
1835             @param mp The "b" value from montgomery_setup()
1836             @return PS_SUCCESS on success
1837             */
1838 245734           static int32_t eccProjectiveAddPoint(psPool_t *pool, const psEccPoint_t *P,
1839             const psEccPoint_t *Q, psEccPoint_t *R,
1840             const pstm_int *modulus, const pstm_digit *mp, pstm_int *tmp_int)
1841             {
1842             pstm_int t1, t2, x, y, z;
1843             pstm_digit *paD;
1844             int32 err;
1845             uint32 paDlen;
1846              
1847 245734           paD = NULL;
1848 245734 50         if (pstm_init_size(pool, &t1, P->x.alloc) < 0)
1849             {
1850 0           return PS_MEM_FAIL;
1851             }
1852 245734           err = PS_MEM_FAIL;
1853 245734 50         if (pstm_init_size(pool, &t2, P->x.alloc) < 0)
1854             {
1855 0           goto ERR_T1;
1856             }
1857 245734 50         if (pstm_init_size(pool, &x, P->x.alloc) < 0)
1858             {
1859 0           goto ERR_T2;
1860             }
1861 245734 50         if (pstm_init_size(pool, &y, P->y.alloc) < 0)
1862             {
1863 0           goto ERR_X;
1864             }
1865 245734 50         if (pstm_init_size(pool, &z, P->z.alloc) < 0)
1866             {
1867 0           goto ERR_Y;
1868             }
1869              
1870             /* should we dbl instead? */
1871 245734 50         if ((err = pstm_sub(modulus, &Q->y, &t1)) != PS_SUCCESS)
1872             {
1873 0           goto done;
1874             }
1875              
1876 245734           if ((pstm_cmp(&P->x, &Q->x) == PSTM_EQ) &&
1877             /* (&Q->z != NULL && pstm_cmp(&P->z, &Q->z) == PSTM_EQ) && */
1878 0 0         (pstm_cmp(&P->z, &Q->z) == PSTM_EQ) &&
1879 0 0         (pstm_cmp(&P->y, &Q->y) == PSTM_EQ ||
1880 0           pstm_cmp(&P->y, &t1) == PSTM_EQ))
1881             {
1882 0           pstm_clear_multi(&t1, &t2, &x, &y, &z, NULL, NULL, NULL);
1883 0           return eccProjectiveDblPoint(pool, P, R, modulus, mp, tmp_int);
1884             }
1885              
1886 245734 50         if ((err = pstm_copy(&P->x, &x)) != PS_SUCCESS)
1887             {
1888 0           goto done;
1889             }
1890 245734 50         if ((err = pstm_copy(&P->y, &y)) != PS_SUCCESS)
1891             {
1892 0           goto done;
1893             }
1894 245734 50         if ((err = pstm_copy(&P->z, &z)) != PS_SUCCESS)
1895             {
1896 0           goto done;
1897             }
1898              
1899             /*
1900             Pre-allocated digit. Used for mul, sqr, AND reduce*/
1901 245734           paDlen = (modulus->used * 2 + 1) * sizeof(pstm_digit);
1902 245734 50         if ((paD = psMalloc(pool, paDlen)) == NULL)
1903             {
1904 0           err = PS_MEM_FAIL;
1905 0           goto done;
1906             }
1907              
1908             /* if Z is one then these are no-operations */
1909 245734 50         if (pstm_cmp_d(&Q->z, 1) != PSTM_EQ)
1910             {
1911             /* T1 = Z' * Z' */
1912 245734 50         if ((err = pstm_sqr_comba(pool, &Q->z, &t1, paD, paDlen))
1913             != PS_SUCCESS)
1914             {
1915 0           goto done;
1916             }
1917 245734 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
1918             != PS_SUCCESS)
1919             {
1920 0           goto done;
1921             }
1922             /* X = X * T1 */
1923 245734 50         if ((err = pstm_mul_comba(pool, &t1, &x, &x, paD, paDlen))
1924             != PS_SUCCESS)
1925             {
1926 0           goto done;
1927             }
1928 245734 50         if ((err = pstm_montgomery_reduce(pool, &x, modulus, *mp, paD, paDlen))
1929             != PS_SUCCESS)
1930             {
1931 0           goto done;
1932             }
1933             /* T1 = Z' * T1 */
1934 245734 50         if ((err = pstm_mul_comba(pool, &Q->z, &t1, &t1, paD, paDlen))
1935             != PS_SUCCESS)
1936             {
1937 0           goto done;
1938             }
1939 245734 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
1940             != PS_SUCCESS)
1941             {
1942 0           goto done;
1943             }
1944             /* Y = Y * T1 */
1945 245734 50         if ((err = pstm_mul_comba(pool, &t1, &y, &y, paD, paDlen))
1946             != PS_SUCCESS)
1947             {
1948 0           goto done;
1949             }
1950 245734 50         if ((err = pstm_montgomery_reduce(pool, &y, modulus, *mp, paD, paDlen))
1951             != PS_SUCCESS)
1952             {
1953 0           goto done;
1954             }
1955             }
1956              
1957             /* T1 = Z*Z */
1958 245734 50         if ((err = pstm_sqr_comba(pool, &z, &t1, paD, paDlen)) != PS_SUCCESS)
1959             {
1960 0           goto done;
1961             }
1962 245734 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
1963             != PS_SUCCESS)
1964             {
1965 0           goto done;
1966             }
1967             /* T2 = X' * T1 */
1968 245734 50         if ((err = pstm_mul_comba(pool, &Q->x, &t1, &t2, paD, paDlen))
1969             != PS_SUCCESS)
1970             {
1971 0           goto done;
1972             }
1973 245734 50         if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen))
1974             != PS_SUCCESS)
1975             {
1976 0           goto done;
1977             }
1978             /* T1 = Z * T1 */
1979 245734 50         if ((err = pstm_mul_comba(pool, &z, &t1, &t1, paD, paDlen)) != PS_SUCCESS)
1980             {
1981 0           goto done;
1982             }
1983 245734 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
1984             != PS_SUCCESS)
1985             {
1986 0           goto done;
1987             }
1988             /* T1 = Y' * T1 */
1989 245734 50         if ((err = pstm_mul_comba(pool, &Q->y, &t1, &t1, paD, paDlen))
1990             != PS_SUCCESS)
1991             {
1992 0           goto done;
1993             }
1994 245734 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
1995             != PS_SUCCESS)
1996             {
1997 0           goto done;
1998             }
1999              
2000             /* Y = Y - T1 */
2001 245734 50         if ((err = pstm_sub(&y, &t1, &y)) != PS_SUCCESS)
2002             {
2003 0           goto done;
2004             }
2005 245734 100         if (pstm_cmp_d(&y, 0) == PSTM_LT)
2006             {
2007 108048 50         if ((err = pstm_add(&y, modulus, &y)) != PS_SUCCESS)
2008             {
2009 0           goto done;
2010             }
2011             }
2012             /* T1 = 2T1 */
2013 245734 50         if ((err = pstm_add(&t1, &t1, &t1)) != PS_SUCCESS)
2014             {
2015 0           goto done;
2016             }
2017 245734 100         if (pstm_cmp(&t1, modulus) != PSTM_LT)
2018             {
2019 120799 50         if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS)
2020             {
2021 0           goto done;
2022             }
2023             }
2024             /* T1 = Y + T1 */
2025 245734 50         if ((err = pstm_add(&t1, &y, &t1)) != PS_SUCCESS)
2026             {
2027 0           goto done;
2028             }
2029 245734 100         if (pstm_cmp(&t1, modulus) != PSTM_LT)
2030             {
2031 117179 50         if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS)
2032             {
2033 0           goto done;
2034             }
2035             }
2036             /* X = X - T2 */
2037 245734 50         if ((err = pstm_sub(&x, &t2, &x)) != PS_SUCCESS)
2038             {
2039 0           goto done;
2040             }
2041 245734 100         if (pstm_cmp_d(&x, 0) == PSTM_LT)
2042             {
2043 113436 50         if ((err = pstm_add(&x, modulus, &x)) != PS_SUCCESS)
2044             {
2045 0           goto done;
2046             }
2047             }
2048             /* T2 = 2T2 */
2049 245734 50         if ((err = pstm_add(&t2, &t2, &t2)) != PS_SUCCESS)
2050             {
2051 0           goto done;
2052             }
2053 245734 100         if (pstm_cmp(&t2, modulus) != PSTM_LT)
2054             {
2055 114465 50         if ((err = pstm_sub(&t2, modulus, &t2)) != PS_SUCCESS)
2056             {
2057 0           goto done;
2058             }
2059             }
2060             /* T2 = X + T2 */
2061 245734 50         if ((err = pstm_add(&t2, &x, &t2)) != PS_SUCCESS)
2062             {
2063 0           goto done;
2064             }
2065 245734 100         if (pstm_cmp(&t2, modulus) != PSTM_LT)
2066             {
2067 116974 50         if ((err = pstm_sub(&t2, modulus, &t2)) != PS_SUCCESS)
2068             {
2069 0           goto done;
2070             }
2071             }
2072              
2073             /* if Z' != 1 */
2074 245734 50         if (pstm_cmp_d(&Q->z, 1) != PSTM_EQ)
2075             {
2076             /* Z = Z * Z' */
2077 245734 50         if ((err = pstm_mul_comba(pool, &z, &Q->z, &z, paD, paDlen))
2078             != PS_SUCCESS)
2079             {
2080 0           goto done;
2081             }
2082 245734 50         if ((err = pstm_montgomery_reduce(pool, &z, modulus, *mp, paD, paDlen))
2083             != PS_SUCCESS)
2084             {
2085 0           goto done;
2086             }
2087             }
2088              
2089             /* Z = Z * X */
2090 245734 50         if ((err = pstm_mul_comba(pool, &z, &x, &z, paD, paDlen)) != PS_SUCCESS)
2091             {
2092 0           goto done;
2093             }
2094 245734 50         if ((err = pstm_montgomery_reduce(pool, &z, modulus, *mp, paD, paDlen))
2095             != PS_SUCCESS)
2096             {
2097 0           goto done;
2098             }
2099              
2100             /* T1 = T1 * X */
2101 245734 50         if ((err = pstm_mul_comba(pool, &t1, &x, &t1, paD, paDlen)) != PS_SUCCESS)
2102             {
2103 0           goto done;
2104             }
2105 245734 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
2106             != PS_SUCCESS)
2107             {
2108 0           goto done;
2109             }
2110             /* X = X * X */
2111 245734 50         if ((err = pstm_sqr_comba(pool, &x, &x, paD, paDlen)) != PS_SUCCESS)
2112             {
2113 0           goto done;
2114             }
2115 245734 50         if ((err = pstm_montgomery_reduce(pool, &x, modulus, *mp, paD, paDlen))
2116             != PS_SUCCESS)
2117             {
2118 0           goto done;
2119             }
2120             /* T2 = T2 * x */
2121 245734 50         if ((err = pstm_mul_comba(pool, &t2, &x, &t2, paD, paDlen)) != PS_SUCCESS)
2122             {
2123 0           goto done;
2124             }
2125 245734 50         if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen))
2126             != PS_SUCCESS)
2127             {
2128 0           goto done;
2129             }
2130             /* T1 = T1 * X */
2131 245734 50         if ((err = pstm_mul_comba(pool, &t1, &x, &t1, paD, paDlen)) != PS_SUCCESS)
2132             {
2133 0           goto done;
2134             }
2135 245734 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
2136             != PS_SUCCESS)
2137             {
2138 0           goto done;
2139             }
2140              
2141             /* X = Y*Y */
2142 245734 50         if ((err = pstm_sqr_comba(pool, &y, &x, paD, paDlen)) != PS_SUCCESS)
2143             {
2144 0           goto done;
2145             }
2146 245734 50         if ((err = pstm_montgomery_reduce(pool, &x, modulus, *mp, paD, paDlen))
2147             != PS_SUCCESS)
2148             {
2149 0           goto done;
2150             }
2151             /* X = X - T2 */
2152 245734 50         if ((err = pstm_sub(&x, &t2, &x)) != PS_SUCCESS)
2153             {
2154 0           goto done;
2155             }
2156 245734 100         if (pstm_cmp_d(&x, 0) == PSTM_LT)
2157             {
2158 129332 50         if ((err = pstm_add(&x, modulus, &x)) != PS_SUCCESS)
2159             {
2160 0           goto done;
2161             }
2162             }
2163              
2164             /* T2 = T2 - X */
2165 245734 50         if ((err = pstm_sub(&t2, &x, &t2)) != PS_SUCCESS)
2166             {
2167 0           goto done;
2168             }
2169 245734 100         if (pstm_cmp_d(&t2, 0) == PSTM_LT)
2170             {
2171 120598 50         if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS)
2172             {
2173 0           goto done;
2174             }
2175             }
2176             /* T2 = T2 - X */
2177 245734 50         if ((err = pstm_sub(&t2, &x, &t2)) != PS_SUCCESS)
2178             {
2179 0           goto done;
2180             }
2181 245734 100         if (pstm_cmp_d(&t2, 0) == PSTM_LT)
2182             {
2183 110753 50         if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS)
2184             {
2185 0           goto done;
2186             }
2187             }
2188             /* T2 = T2 * Y */
2189 245734 50         if ((err = pstm_mul_comba(pool, &t2, &y, &t2, paD, paDlen)) != PS_SUCCESS)
2190             {
2191 0           goto done;
2192             }
2193 245734 50         if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen))
2194             != PS_SUCCESS)
2195             {
2196 0           goto done;
2197             }
2198             /* Y = T2 - T1 */
2199 245734 50         if ((err = pstm_sub(&t2, &t1, &y)) != PS_SUCCESS)
2200             {
2201 0           goto done;
2202             }
2203 245734 100         if (pstm_cmp_d(&y, 0) == PSTM_LT)
2204             {
2205 123892 50         if ((err = pstm_add(&y, modulus, &y)) != PS_SUCCESS)
2206             {
2207 0           goto done;
2208             }
2209             }
2210             /* Y = Y/2 */
2211 245734 50         if (pstm_isodd(&y))
    100          
2212             {
2213 113542 50         if ((err = pstm_add(&y, modulus, &y)) != PS_SUCCESS)
2214             {
2215 0           goto done;
2216             }
2217             }
2218 245734 50         if ((err = pstm_div_2(&y, &y)) != PS_SUCCESS)
2219             {
2220 0           goto done;
2221             }
2222              
2223 245734 50         if ((err = pstm_copy(&x, &R->x)) != PS_SUCCESS)
2224             {
2225 0           goto done;
2226             }
2227 245734 50         if ((err = pstm_copy(&y, &R->y)) != PS_SUCCESS)
2228             {
2229 0           goto done;
2230             }
2231 245734 50         if ((err = pstm_copy(&z, &R->z)) != PS_SUCCESS)
2232             {
2233 0           goto done;
2234             }
2235              
2236 245734           err = PS_SUCCESS;
2237              
2238             done:
2239 245734           pstm_clear(&z);
2240             ERR_Y:
2241 245734           pstm_clear(&y);
2242             ERR_X:
2243 245734           pstm_clear(&x);
2244             ERR_T2:
2245 245734           pstm_clear(&t2);
2246             ERR_T1:
2247 245734           pstm_clear(&t1);
2248 245734 50         if (paD)
2249             {
2250 245734           psFree(paD, pool);
2251             }
2252 245734           return err;
2253             }
2254              
2255              
2256             /******************************************************************************/
2257             /**
2258             Double an ECC point
2259             @param[in] P The point to double
2260             @param[out] R The destination of the double
2261             @param[in] modulus The modulus of the field the ECC curve is in
2262             @param[in] mp The "b" value from montgomery_setup()
2263             @param[in] A The "A" of the field the ECC curve is in
2264             @return PS_SUCCESS on success
2265             */
2266 1110207           static int32_t eccProjectiveDblPoint(psPool_t *pool, const psEccPoint_t *P,
2267             psEccPoint_t *R, const pstm_int *modulus, const pstm_digit *mp,
2268             const pstm_int *A)
2269             {
2270             pstm_int t1, t2;
2271             pstm_digit *paD;
2272             uint32 paDlen;
2273             int32 err, initSize;
2274              
2275              
2276 1110207 100         if (P != R)
2277             {
2278 2142 50         if (pstm_copy(&P->x, &R->x) < 0)
2279             {
2280 0           return PS_MEM_FAIL;
2281             }
2282 2142 50         if (pstm_copy(&P->y, &R->y) < 0)
2283             {
2284 0           return PS_MEM_FAIL;
2285             }
2286 2142 50         if (pstm_copy(&P->z, &R->z) < 0)
2287             {
2288 0           return PS_MEM_FAIL;
2289             }
2290             }
2291              
2292 1110207           initSize = R->x.used;
2293 1110207 100         if (R->y.used > initSize)
2294             {
2295 1337           initSize = R->y.used;
2296             }
2297 1110207 50         if (R->z.used > initSize)
2298             {
2299 0           initSize = R->z.used;
2300             }
2301              
2302 1110207 50         if (pstm_init_size(pool, &t1, (initSize * 2) + 1) < 0)
2303             {
2304 0           return PS_MEM_FAIL;
2305             }
2306 1110207 50         if (pstm_init_size(pool, &t2, (initSize * 2) + 1) < 0)
2307             {
2308 0           pstm_clear(&t1);
2309 0           return PS_MEM_FAIL;
2310             }
2311              
2312             /*
2313             Pre-allocated digit. Used for mul, sqr, AND reduce*/
2314 1110207           paDlen = (modulus->used * 2 + 1) * sizeof(pstm_digit);
2315 1110207 50         if ((paD = psMalloc(pool, paDlen)) == NULL)
2316             {
2317 0           err = PS_MEM_FAIL;
2318 0           goto done;
2319             }
2320              
2321             /* t1 = Z * Z */
2322 1110207 50         if ((err = pstm_sqr_comba(pool, &R->z, &t1, paD, paDlen)) != PS_SUCCESS)
2323             {
2324 0           goto done;
2325             }
2326 1110207 50         if ((err = pstm_montgomery_reduce(pool, &t1, modulus, *mp, paD, paDlen))
2327             != PS_SUCCESS)
2328             {
2329 0           goto done;
2330             }
2331             /* Z = Y * Z */
2332 1110207 50         if ((err = pstm_mul_comba(pool, &R->z, &R->y, &R->z, paD, paDlen))
2333             != PS_SUCCESS)
2334             {
2335 0           goto done;
2336             }
2337 1110207 50         if ((err = pstm_montgomery_reduce(pool, &R->z, modulus, *mp, paD, paDlen))
2338             != PS_SUCCESS)
2339             {
2340 0           goto done;
2341             }
2342             /* Z = 2Z */
2343 1110207 50         if ((err = pstm_add(&R->z, &R->z, &R->z)) != PS_SUCCESS)
2344             {
2345 0           goto done;
2346             }
2347 1110207 100         if (pstm_cmp(&R->z, modulus) != PSTM_LT)
2348             {
2349 537122 50         if ((err = pstm_sub(&R->z, modulus, &R->z)) != PS_SUCCESS)
2350             {
2351 0           goto done;
2352             }
2353             }
2354              
2355             /* compute into T1 M=3(X+Z^2)(X-Z^2) */
2356 1110207 50         if (A == NULL)
2357             {
2358             /* T2 = X - T1 */
2359 1110207 50         if ((err = pstm_sub(&R->x, &t1, &t2)) != PS_SUCCESS)
2360             {
2361 0           goto done;
2362             }
2363 1110207 100         if (pstm_cmp_d(&t2, 0) == PSTM_LT)
2364             {
2365 577888 50         if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS)
2366             {
2367 0           goto done;
2368             }
2369             }
2370             /* T1 = X + T1 */
2371 1110207 50         if ((err = pstm_add(&t1, &R->x, &t1)) != PS_SUCCESS)
2372             {
2373 0           goto done;
2374             }
2375 1110207 100         if (pstm_cmp(&t1, modulus) != PSTM_LT)
2376             {
2377 533544 50         if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS)
2378             {
2379 0           goto done;
2380             }
2381             }
2382             /* T2 = T1 * T2 */
2383 1110207 50         if ((err = pstm_mul_comba(pool, &t1, &t2, &t2, paD, paDlen)) != PS_SUCCESS)
2384             {
2385 0           goto done;
2386             }
2387 1110207 50         if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen))
2388             != PS_SUCCESS)
2389             {
2390 0           goto done;
2391             }
2392             /* T1 = 2T2 */
2393 1110207 50         if ((err = pstm_add(&t2, &t2, &t1)) != PS_SUCCESS)
2394             {
2395 0           goto done;
2396             }
2397 1110207 100         if (pstm_cmp(&t1, modulus) != PSTM_LT)
2398             {
2399 542035 50         if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS)
2400             {
2401 0           goto done;
2402             }
2403             }
2404             /* T1 = T1 + T2 */
2405 1110207 50         if ((err = pstm_add(&t1, &t2, &t1)) != PS_SUCCESS)
2406             {
2407 0           goto done;
2408             }
2409 1110207 100         if (pstm_cmp(&t1, modulus) != PSTM_LT)
2410             {
2411 567417 50         if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS)
2412             {
2413 0           goto done;
2414             }
2415             }
2416             }
2417             else
2418             {
2419             /* compute into T1 M=3X^2 + A Z^4 */
2420             pstm_int t3, t4;
2421              
2422 0 0         if (pstm_init_size(pool, &t3, (initSize * 2) + 1) < 0)
2423             {
2424 0           return PS_MEM_FAIL;
2425             }
2426 0 0         if (pstm_init_size(pool, &t4, (initSize * 2) + 1) < 0)
2427             {
2428 0           pstm_clear(&t3);
2429 0           return PS_MEM_FAIL;
2430             }
2431              
2432             /* T3 = X * X */
2433 0 0         if ((err = pstm_sqr_comba(pool, &R->x, &t3, paD, paDlen)) != PS_SUCCESS)
2434             {
2435 0           goto done;
2436             }
2437 0 0         if ((err = pstm_montgomery_reduce(pool, &t3, modulus, *mp, paD, paDlen))
2438             != PS_SUCCESS)
2439             {
2440 0           goto done;
2441             }
2442              
2443             /* T4 = 2T3 */
2444 0 0         if ((err = pstm_add(&t3, &t3, &t4)) != PS_SUCCESS)
2445             {
2446 0           goto done;
2447             }
2448 0 0         if (pstm_cmp(&t4, modulus) != PSTM_LT)
2449             {
2450 0 0         if ((err = pstm_sub(&t4, modulus, &t4)) != PS_SUCCESS)
2451             {
2452 0           goto done;
2453             }
2454             }
2455              
2456             /* T3 = T3 + T4 */
2457 0 0         if ((err = pstm_add(&t3, &t4, &t3)) != PS_SUCCESS)
2458             {
2459 0           goto done;
2460             }
2461 0 0         if (pstm_cmp(&t3, modulus) != PSTM_LT)
2462             {
2463 0 0         if ((err = pstm_sub(&t3, modulus, &t3)) != PS_SUCCESS)
2464             {
2465 0           goto done;
2466             }
2467             }
2468              
2469             /* T4 = T1 * T1 */
2470 0 0         if ((err = pstm_sqr_comba(pool, &t1, &t4, paD, paDlen)) != PS_SUCCESS)
2471             {
2472 0           goto done;
2473             }
2474 0 0         if ((err = pstm_mod(pool, &t4, modulus, &t4)) != PS_SUCCESS)
2475             {
2476 0           goto done;
2477             }
2478              
2479             /* T4 = T4 * A */
2480 0 0         if ((err = pstm_mul_comba(pool, &t4, A, &t4, paD, paDlen)) != PS_SUCCESS)
2481             {
2482 0           goto done;
2483             }
2484              
2485 0 0         if ((err = pstm_montgomery_reduce(pool, &t4, modulus, *mp, paD, paDlen))
2486             != PS_SUCCESS)
2487             {
2488 0           goto done;
2489             }
2490              
2491             /* T1 = T3 + T4 */
2492 0 0         if ((err = pstm_add(&t3, &t4, &t1)) != PS_SUCCESS)
2493             {
2494 0           goto done;
2495             }
2496 0 0         if (pstm_cmp(&t1, modulus) != PSTM_LT)
2497             {
2498 0 0         if ((err = pstm_sub(&t1, modulus, &t1)) != PS_SUCCESS)
2499             {
2500 0           goto done;
2501             }
2502             }
2503              
2504 0           pstm_clear_multi(&t3, &t4, NULL, NULL, NULL, NULL, NULL, NULL);
2505             }
2506              
2507             /* Y = 2Y */
2508 1110207 50         if ((err = pstm_add(&R->y, &R->y, &R->y)) != PS_SUCCESS)
2509             {
2510 0           goto done;
2511             }
2512 1110207 100         if (pstm_cmp(&R->y, modulus) != PSTM_LT)
2513             {
2514 558135 50         if ((err = pstm_sub(&R->y, modulus, &R->y)) != PS_SUCCESS)
2515             {
2516 0           goto done;
2517             }
2518             }
2519             /* Y = Y * Y */
2520 1110207 50         if ((err = pstm_sqr_comba(pool, &R->y, &R->y, paD, paDlen)) != PS_SUCCESS)
2521             {
2522 0           goto done;
2523             }
2524 1110207 50         if ((err = pstm_montgomery_reduce(pool, &R->y, modulus, *mp, paD, paDlen))
2525             != PS_SUCCESS)
2526             {
2527 0           goto done;
2528             }
2529             /* T2 = Y * Y */
2530 1110207 50         if ((err = pstm_sqr_comba(pool, &R->y, &t2, paD, paDlen)) != PS_SUCCESS)
2531             {
2532 0           goto done;
2533             }
2534 1110207 50         if ((err = pstm_montgomery_reduce(pool, &t2, modulus, *mp, paD, paDlen))
2535             != PS_SUCCESS)
2536             {
2537 0           goto done;
2538             }
2539             /* T2 = T2/2 */
2540 1110207 50         if (pstm_isodd(&t2))
    100          
2541             {
2542 566850 50         if ((err = pstm_add(&t2, modulus, &t2)) != PS_SUCCESS)
2543             {
2544 0           goto done;
2545             }
2546             }
2547 1110207 50         if ((err = pstm_div_2(&t2, &t2)) != PS_SUCCESS)
2548             {
2549 0           goto done;
2550             }
2551             /* Y = Y * X */
2552 1110207 50         if ((err = pstm_mul_comba(pool, &R->y, &R->x, &R->y, paD, paDlen))
2553             != PS_SUCCESS)
2554             {
2555 0           goto done;
2556             }
2557 1110207 50         if ((err = pstm_montgomery_reduce(pool, &R->y, modulus, *mp, paD, paDlen))
2558             != PS_SUCCESS)
2559             {
2560 0           goto done;
2561             }
2562              
2563             /* X = T1 * T1 */
2564 1110207 50         if ((err = pstm_sqr_comba(pool, &t1, &R->x, paD, paDlen)) != PS_SUCCESS)
2565             {
2566 0           goto done;
2567             }
2568 1110207 50         if ((err = pstm_montgomery_reduce(pool, &R->x, modulus, *mp, paD, paDlen))
2569             != PS_SUCCESS)
2570             {
2571 0           goto done;
2572             }
2573             /* X = X - Y */
2574 1110207 50         if ((err = pstm_sub(&R->x, &R->y, &R->x)) != PS_SUCCESS)
2575             {
2576 0           goto done;
2577             }
2578 1110207 100         if (pstm_cmp_d(&R->x, 0) == PSTM_LT)
2579             {
2580 561429 50         if ((err = pstm_add(&R->x, modulus, &R->x)) != PS_SUCCESS)
2581             {
2582 0           goto done;
2583             }
2584             }
2585             /* X = X - Y */
2586 1110207 50         if ((err = pstm_sub(&R->x, &R->y, &R->x)) != PS_SUCCESS)
2587             {
2588 0           goto done;
2589             }
2590 1110207 100         if (pstm_cmp_d(&R->x, 0) == PSTM_LT)
2591             {
2592 553863 50         if ((err = pstm_add(&R->x, modulus, &R->x)) != PS_SUCCESS)
2593             {
2594 0           goto done;
2595             }
2596             }
2597              
2598             /* Y = Y - X */
2599 1110207 50         if ((err = pstm_sub(&R->y, &R->x, &R->y)) != PS_SUCCESS)
2600             {
2601 0           goto done;
2602             }
2603 1110207 100         if (pstm_cmp_d(&R->y, 0) == PSTM_LT)
2604             {
2605 524235 50         if ((err = pstm_add(&R->y, modulus, &R->y)) != PS_SUCCESS)
2606             {
2607 0           goto done;
2608             }
2609             }
2610             /* Y = Y * T1 */
2611 1110207 50         if ((err = pstm_mul_comba(pool, &R->y, &t1, &R->y, paD, paDlen))
2612             != PS_SUCCESS)
2613             {
2614 0           goto done;
2615             }
2616 1110207 50         if ((err = pstm_montgomery_reduce(pool, &R->y, modulus, *mp, paD, paDlen))
2617             != PS_SUCCESS)
2618             {
2619 0           goto done;
2620             }
2621             /* Y = Y - T2 */
2622 1110207 50         if ((err = pstm_sub(&R->y, &t2, &R->y)) != PS_SUCCESS)
2623             {
2624 0           goto done;
2625             }
2626 1110207 100         if (pstm_cmp_d(&R->y, 0) == PSTM_LT)
2627             {
2628 574032 50         if ((err = pstm_add(&R->y, modulus, &R->y)) != PS_SUCCESS)
2629             {
2630 0           goto done;
2631             }
2632             }
2633              
2634 1110207           err = PS_SUCCESS;
2635             done:
2636 1110207           pstm_clear_multi(&t1, &t2, NULL, NULL, NULL, NULL, NULL, NULL);
2637 1110207 50         if (paD)
2638             {
2639 1110207           psFree(paD, pool);
2640             }
2641 1110207           return err;
2642             }
2643              
2644             /******************************************************************************/
2645             /**
2646             Allocate a new ECC point.
2647             @return A newly allocated point or NULL on error
2648             */
2649 21420           static psEccPoint_t *eccNewPoint(psPool_t *pool, short size)
2650             {
2651 21420           psEccPoint_t *p = NULL;
2652              
2653 21420           p = psMalloc(pool, sizeof(psEccPoint_t));
2654 21420 50         if (p == NULL)
2655             {
2656 0           return NULL;
2657             }
2658 21420           p->pool = pool;
2659 21420 50         if (size == 0)
2660             {
2661 0 0         if (pstm_init(pool, &p->x) != PSTM_OKAY)
2662             {
2663 0           goto ERR;
2664             }
2665 0 0         if (pstm_init(pool, &p->y) != PSTM_OKAY)
2666             {
2667 0           goto ERR_X;
2668             }
2669 0 0         if (pstm_init(pool, &p->z) != PSTM_OKAY)
2670             {
2671 0           goto ERR_Y;
2672             }
2673             }
2674             else
2675             {
2676 21420 50         if (pstm_init_size(pool, &p->x, size) != PSTM_OKAY)
2677             {
2678 0           goto ERR;
2679             }
2680 21420 50         if (pstm_init_size(pool, &p->y, size) != PSTM_OKAY)
2681             {
2682 0           goto ERR_X;
2683             }
2684 21420 50         if (pstm_init_size(pool, &p->z, size) != PSTM_OKAY)
2685             {
2686 0           goto ERR_Y;
2687             }
2688             }
2689 21420           return p;
2690             ERR_Y:
2691 0           pstm_clear(&p->y);
2692             ERR_X:
2693 0           pstm_clear(&p->x);
2694             ERR:
2695 0           psFree(p, pool);
2696 0           return NULL;
2697             }
2698              
2699             /**
2700             Free an ECC point from memory.
2701             @param p The point to free
2702             */
2703 21420           static void eccFreePoint(psEccPoint_t *p)
2704             {
2705 21420 50         if (p != NULL)
2706             {
2707 21420           pstm_clear(&p->x);
2708 21420           pstm_clear(&p->y);
2709 21420           pstm_clear(&p->z);
2710 21420           psFree(p, p->pool);
2711             }
2712 21420           }
2713              
2714             /**
2715             Map a projective jacbobian point back to affine space
2716             @param[in,out] P [in/out] The point to map
2717             @param[in] modulus The modulus of the field the ECC curve is in
2718             @param[in] mp The "b" value from montgomery_setup()
2719             @return PS_SUCCESS on success
2720             */
2721 2142           static int32_t eccMap(psPool_t *pool, psEccPoint_t *P, const pstm_int *modulus,
2722             const pstm_digit *mp)
2723             {
2724             pstm_int t1, t2;
2725             pstm_digit *paD;
2726             int32 err;
2727             uint32 paDlen;
2728              
2729 2142 50         if (pstm_init_size(pool, &t1, P->x.alloc) < 0)
2730             {
2731 0           return PS_MEM_FAIL;
2732             }
2733 2142 50         if (pstm_init_size(pool, &t2, P->x.alloc) < 0)
2734             {
2735 0           pstm_clear(&t1);
2736 0           return PS_MEM_FAIL;
2737             }
2738              
2739             /* Pre-allocated digit. Used for mul, sqr, AND reduce */
2740 2142           paDlen = (modulus->used * 2 + 1) * sizeof(pstm_digit);
2741 2142 50         if ((paD = psMalloc(pool, paDlen)) == NULL)
2742             {
2743 0           err = PS_MEM_FAIL;
2744 0           goto done;
2745             }
2746              
2747             /* first map z back to normal */
2748 2142 50         if ((err = pstm_montgomery_reduce(pool, &P->z, modulus, *mp, paD, paDlen))
2749             != PS_SUCCESS)
2750             {
2751 0           goto done;
2752             }
2753              
2754             /* get 1/z */
2755 2142 50         if ((err = pstm_invmod(pool, &P->z, modulus, &t1)) != PS_SUCCESS)
2756             {
2757 0           goto done;
2758             }
2759              
2760             /* get 1/z^2 and 1/z^3 */
2761 2142 50         if ((err = pstm_sqr_comba(pool, &t1, &t2, paD, paDlen)) != PS_SUCCESS)
2762             {
2763 0           goto done;
2764             }
2765 2142 50         if ((err = pstm_mod(pool, &t2, modulus, &t2)) != PS_SUCCESS)
2766             {
2767 0           goto done;
2768             }
2769 2142 50         if ((err = pstm_mul_comba(pool, &t1, &t2, &t1, paD, paDlen)) != PS_SUCCESS)
2770             {
2771 0           goto done;
2772             }
2773 2142 50         if ((err = pstm_mod(pool, &t1, modulus, &t1)) != PS_SUCCESS)
2774             {
2775 0           goto done;
2776             }
2777              
2778             /* multiply against x/y */
2779 2142 50         if ((err = pstm_mul_comba(pool, &P->x, &t2, &P->x, paD, paDlen))
2780             != PS_SUCCESS)
2781             {
2782 0           goto done;
2783             }
2784 2142 50         if ((err = pstm_montgomery_reduce(pool, &P->x, modulus, *mp, paD, paDlen))
2785             != PS_SUCCESS)
2786             {
2787 0           goto done;
2788             }
2789 2142 50         if ((err = pstm_mul_comba(pool, &P->y, &t1, &P->y, paD, paDlen))
2790             != PS_SUCCESS)
2791             {
2792 0           goto done;
2793             }
2794 2142 50         if ((err = pstm_montgomery_reduce(pool, &P->y, modulus, *mp, paD, paDlen))
2795             != PS_SUCCESS)
2796             {
2797 0           goto done;
2798             }
2799 2142           pstm_set(&P->z, 1);
2800 2142           err = PS_SUCCESS;
2801             done:
2802 2142           pstm_clear_multi(&t1, &t2, NULL, NULL, NULL, NULL, NULL, NULL);
2803 2142 50         if (paD)
2804             {
2805 2142           psFree(paD, pool);
2806             }
2807 2142           return err;
2808             }
2809              
2810             /******************************************************************************/
2811             /**
2812             Verify an ECDSA signature.
2813              
2814             @param pool Memory pool
2815             @param[in] key Public key to use for signature validation
2816             @param[in] buf Data that is signed by private 'key'
2817             @param[in] buflen Length in bytes of 'buf'
2818             @param[in] sig Signature of 'buf' by the private key pair of 'key'
2819             @param[in] siglen Length in bytes of 'sig'
2820             @param[out] status Result of the signature check. 1 on success, -1 on
2821             non-matching signature.
2822             @param usrData Data used by some hardware crypto. Can be NULL.
2823             @return < 0 on failure. Also 'status'.
2824             */
2825 0           int32_t psEccDsaVerify(psPool_t *pool, const psEccKey_t *key,
2826             const unsigned char *buf, psSize_t buflen,
2827             const unsigned char *sig, psSize_t siglen,
2828             int32_t *status, void *usrData)
2829             {
2830             psEccPoint_t *mG, *mQ;
2831             pstm_digit mp;
2832 0           pstm_int *A = NULL;
2833             pstm_int v, w, u1, u2, e, p, m, r, s;
2834             const unsigned char *c, *end;
2835             int32_t err, radlen;
2836             psSize_t len;
2837              
2838             /* default to invalid signature */
2839 0           *status = -1;
2840              
2841 0           c = sig;
2842 0           end = c + siglen;
2843              
2844 0 0         if ((err = getAsnSequence(&c, (uint16_t) (end - c), &len)) < 0)
2845             {
2846             psTraceCrypto("ECDSA subject signature parse failure 1\n");
2847 0           return err;
2848             }
2849 0 0         if ((err = pstm_read_asn(pool, &c, (uint16_t) (end - c), &r)) < 0)
2850             {
2851             psTraceCrypto("ECDSA subject signature parse failure 2\n");
2852 0           return err;
2853             }
2854 0 0         if ((err = pstm_read_asn(pool, &c, (uint16_t) (end - c), &s)) < 0)
2855             {
2856             psTraceCrypto("ECDSA subject signature parse failure 3\n");
2857 0           pstm_clear(&r);
2858 0           return err;
2859             }
2860              
2861             /* allocate ints */
2862 0           radlen = key->curve->size * 2;
2863 0 0         if (pstm_init_for_read_unsigned_bin(pool, &p, key->curve->size) < 0)
2864             {
2865 0           pstm_clear(&s);
2866 0           pstm_clear(&r);
2867 0           return PS_MEM_FAIL;
2868             }
2869 0           err = PS_MEM_FAIL;
2870 0 0         if (pstm_init_for_read_unsigned_bin(pool, &m, key->curve->size) < 0)
2871             {
2872 0           goto LBL_P;
2873             }
2874 0 0         if (pstm_init_size(pool, &v, key->pubkey.x.alloc) < 0)
2875             {
2876 0           goto LBL_M;
2877             }
2878 0 0         if (pstm_init_size(pool, &w, s.alloc) < 0)
2879             {
2880 0           goto LBL_V;
2881             }
2882             /* Shouldn't have signed more data than the key length. Truncate if so */
2883 0 0         if (buflen > key->curve->size)
2884             {
2885 0           buflen = key->curve->size;
2886             }
2887 0 0         if (pstm_init_for_read_unsigned_bin(pool, &e, buflen) < 0)
2888             {
2889 0           goto LBL_W;
2890             }
2891 0 0         if (pstm_init_size(pool, &u1, e.alloc + w.alloc) < 0)
2892             {
2893 0           goto LBL_E;
2894             }
2895 0 0         if (pstm_init_size(pool, &u2, r.alloc + w.alloc) < 0)
2896             {
2897 0           goto LBL_U1;
2898             }
2899              
2900             /* allocate points */
2901 0 0         if ((mG = eccNewPoint(pool, key->pubkey.x.alloc * 2)) == NULL)
2902             {
2903 0           goto LBL_U2;
2904             }
2905 0 0         if ((mQ = eccNewPoint(pool, key->pubkey.x.alloc * 2)) == NULL)
2906             {
2907 0           goto LBL_MG;
2908             }
2909              
2910             /* get the order */
2911 0 0         if ((err = pstm_read_radix(pool, &p, key->curve->order, radlen, 16))
2912             != PS_SUCCESS)
2913             {
2914 0           goto error;
2915             }
2916              
2917             /* get the modulus */
2918 0 0         if ((err = pstm_read_radix(pool, &m, key->curve->prime, radlen, 16))
2919             != PS_SUCCESS)
2920             {
2921 0           goto error;
2922             }
2923              
2924             /* check for zero */
2925 0 0         if (pstm_iszero(&r) || pstm_iszero(&s) || pstm_cmp(&r, &p) != PSTM_LT ||
    0          
2926 0           pstm_cmp(&s, &p) != PSTM_LT)
2927             {
2928 0           err = PS_PARSE_FAIL;
2929 0           goto error;
2930             }
2931              
2932             /* read data */
2933 0 0         if ((err = pstm_read_unsigned_bin(&e, buf, buflen)) != PS_SUCCESS)
2934             {
2935 0           goto error;
2936             }
2937              
2938             /* w = s^-1 mod n */
2939 0 0         if ((err = pstm_invmod(pool, &s, &p, &w)) != PS_SUCCESS)
2940             {
2941 0           goto error;
2942             }
2943              
2944             /* u1 = ew */
2945 0 0         if ((err = pstm_mulmod(pool, &e, &w, &p, &u1)) != PS_SUCCESS)
2946             {
2947 0           goto error;
2948             }
2949              
2950             /* u2 = rw */
2951 0 0         if ((err = pstm_mulmod(pool, &r, &w, &p, &u2)) != PS_SUCCESS)
2952             {
2953 0           goto error;
2954             }
2955              
2956             /* find mG and mQ */
2957 0 0         if ((err = pstm_read_radix(pool, &mG->x, key->curve->Gx, radlen, 16))
2958             != PS_SUCCESS)
2959             {
2960 0           goto error;
2961             }
2962 0 0         if ((err = pstm_read_radix(pool, &mG->y, key->curve->Gy, radlen, 16))
2963             != PS_SUCCESS)
2964             {
2965 0           goto error;
2966             }
2967 0           pstm_set(&mG->z, 1);
2968              
2969 0 0         if ((err = pstm_copy(&key->pubkey.x, &mQ->x)) != PS_SUCCESS)
2970             {
2971 0           goto error;
2972             }
2973 0 0         if ((err = pstm_copy(&key->pubkey.y, &mQ->y)) != PS_SUCCESS)
2974             {
2975 0           goto error;
2976             }
2977 0 0         if ((err = pstm_copy(&key->pubkey.z, &mQ->z)) != PS_SUCCESS)
2978             {
2979 0           goto error;
2980             }
2981              
2982 0 0         if (key->curve->isOptimized == 0)
2983             {
2984 0 0         if ((A = psMalloc(pool, sizeof(pstm_int))) == NULL)
2985             {
2986 0           goto error;
2987             }
2988              
2989 0 0         if (pstm_init_for_read_unsigned_bin(pool, A, key->curve->size) < 0)
2990             {
2991 0           goto error;
2992             }
2993              
2994 0 0         if ((err = pstm_read_radix(pool, A, key->curve->A,
2995 0           key->curve->size * 2, 16))
2996             != PS_SUCCESS)
2997             {
2998 0           goto error;
2999             }
3000             }
3001              
3002             /* compute u1*mG + u2*mQ = mG */
3003 0 0         if ((err = eccMulmod(pool, &u1, mG, mG, &m, 0, A)) != PS_SUCCESS)
3004             {
3005 0           goto error;
3006             }
3007 0 0         if ((err = eccMulmod(pool, &u2, mQ, mQ, &m, 0, A)) != PS_SUCCESS)
3008             {
3009 0           goto error;
3010             }
3011              
3012             /* find the montgomery mp */
3013 0 0         if ((err = pstm_montgomery_setup(&m, &mp)) != PS_SUCCESS)
3014             {
3015 0           goto error;
3016             }
3017              
3018             /* add them */
3019 0 0         if ((err = eccProjectiveAddPoint(pool, mQ, mG, mG, &m, &mp, A)) != PS_SUCCESS)
3020             {
3021 0           goto error;
3022             }
3023              
3024             /* reduce */
3025 0 0         if ((err = eccMap(pool, mG, &m, &mp)) != PS_SUCCESS)
3026             {
3027 0           goto error;
3028             }
3029              
3030             /* v = X_x1 mod n */
3031 0 0         if ((err = pstm_mod(pool, &mG->x, &p, &v)) != PS_SUCCESS)
3032             {
3033 0           goto error;
3034             }
3035              
3036             /* does v == r */
3037 0 0         if (pstm_cmp(&v, &r) == PSTM_EQ)
3038             {
3039 0           *status = 1;
3040             }
3041              
3042             /* clear up and return */
3043 0           err = PS_SUCCESS;
3044              
3045             error:
3046 0 0         if (A)
3047             {
3048 0           pstm_clear(A);
3049 0           psFree(A, pool);
3050             }
3051              
3052 0           eccFreePoint(mQ);
3053             LBL_MG:
3054 0           eccFreePoint(mG);
3055             LBL_U2:
3056 0           pstm_clear(&u2);
3057             LBL_U1:
3058 0           pstm_clear(&u1);
3059             LBL_E:
3060 0           pstm_clear(&e);
3061             LBL_W:
3062 0           pstm_clear(&w);
3063             LBL_V:
3064 0           pstm_clear(&v);
3065             LBL_M:
3066 0           pstm_clear(&m);
3067             LBL_P:
3068 0           pstm_clear(&p);
3069 0           pstm_clear(&s);
3070 0           pstm_clear(&r);
3071 0           return err;
3072             }
3073              
3074             /**
3075             Sign a message digest.
3076             @param pool Memory pool
3077             @param[in] key Private ECC key
3078             @param[in] in The data to sign
3079             @param[in] inlen The length in bytes of 'in'
3080             @param[out] out The destination for the signature
3081             @param[in,out] outlen The max size and resulting size of the signature
3082             @param[in] includeSize Pass 1 to include size prefix in output.
3083             @param usrData Implementation specific data. Can pass NULL.
3084             @return PS_SUCCESS if successful
3085              
3086             @note TLS does use the size prefix in output.
3087             */
3088 0           int32_t psEccDsaSign(psPool_t *pool, const psEccKey_t *privKey,
3089             const unsigned char *buf, psSize_t buflen,
3090             unsigned char *sig, psSize_t *siglen,
3091             uint8_t includeSize, void *usrData)
3092             {
3093             psEccKey_t pubKey; /* @note Large on the stack */
3094             pstm_int r, s;
3095              
3096             pstm_int e, p;
3097             psSize_t radlen;
3098 0           int32_t err = PS_MEM_FAIL;
3099             psSize_t olen, rLen, sLen;
3100             uint32_t rflag, sflag, sanity;
3101             unsigned char *negative;
3102              
3103 0           rflag = sflag = 0;
3104              
3105             /* is this a private key? */
3106 0 0         if (privKey->type != PS_PRIVKEY)
3107             {
3108 0           return PS_ARG_FAIL;
3109             }
3110              
3111             /* Can't sign more data than the key length. Truncate if so */
3112 0 0         if (buflen > privKey->curve->size)
3113             {
3114 0           buflen = privKey->curve->size;
3115             }
3116              
3117 0           radlen = privKey->curve->size * 2;
3118 0 0         if (pstm_init_for_read_unsigned_bin(pool, &p, privKey->curve->size) < 0)
3119             {
3120 0           return PS_MEM_FAIL;
3121             }
3122 0 0         if (pstm_init_for_read_unsigned_bin(pool, &e, buflen) < 0)
3123             {
3124 0           goto LBL_P;
3125             }
3126 0 0         if (pstm_init_size(pool, &r, p.alloc) < 0)
3127             {
3128 0           goto LBL_E;
3129             }
3130 0 0         if (pstm_init_size(pool, &s, p.alloc) < 0)
3131             {
3132 0           goto LBL_R;
3133             }
3134              
3135 0 0         if ((err = pstm_read_radix(pool, &p, privKey->curve->order, radlen,
3136             16)) != PS_SUCCESS)
3137             {
3138 0           goto errnokey;
3139             }
3140 0 0         if ((err = pstm_read_unsigned_bin(&e, buf, buflen)) != PS_SUCCESS)
3141             {
3142 0           goto errnokey;
3143             }
3144              
3145             /* make up a key and export the public copy */
3146 0           sanity = 0;
3147             for (;; )
3148             {
3149 0 0         if (sanity++ > 99)
3150             {
3151             psTraceCrypto("ECC Signature sanity exceeded. Verify PRNG output.\n");
3152 0           err = PS_PLATFORM_FAIL; /* possible problem with prng */
3153 0           goto errnokey;
3154             }
3155 0 0         if ((err = psEccGenKey(pool, &pubKey, privKey->curve, usrData))
3156             != PS_SUCCESS)
3157             {
3158 0           goto errnokey;
3159             }
3160             /* find r = x1 mod n */
3161 0 0         if ((err = pstm_mod(pool, &pubKey.pubkey.x, &p, &r)) != PS_SUCCESS)
3162             {
3163 0           goto error;
3164             }
3165              
3166 0 0         if (pstm_iszero(&r) == PS_TRUE)
3167             {
3168 0           psEccClearKey(&pubKey);
3169             }
3170             else
3171             {
3172             /* find s = (e + xr)/k */
3173 0 0         if ((err = pstm_invmod(pool, &pubKey.k, &p, &pubKey.k)) !=
3174             PS_SUCCESS)
3175             {
3176 0           goto error; /* k = 1/k */
3177             }
3178 0 0         if ((err = pstm_mulmod(pool, &privKey->k, &r, &p, &s))
3179             != PS_SUCCESS)
3180             {
3181 0           goto error; /* s = xr */
3182             }
3183 0 0         if ((err = pstm_add(&e, &s, &s)) != PS_SUCCESS)
3184             {
3185 0           goto error; /* s = e + xr */
3186             }
3187 0 0         if ((err = pstm_mod(pool, &s, &p, &s)) != PS_SUCCESS)
3188             {
3189 0           goto error; /* s = e + xr */
3190             }
3191 0 0         if ((err = pstm_mulmod(pool, &s, &pubKey.k, &p, &s))
3192             != PS_SUCCESS)
3193             {
3194 0           goto error; /* s = (e + xr)/k */
3195             }
3196 0           psEccClearKey(&pubKey);
3197              
3198 0           rLen = pstm_unsigned_bin_size(&r);
3199 0           sLen = pstm_unsigned_bin_size(&s);
3200              
3201             /* Signatures can be smaller than the keysize but keep it sane */
3202 0 0         if (((rLen + 6) >= privKey->curve->size) &&
    0          
3203 0           ((sLen + 6) >= privKey->curve->size))
3204             {
3205 0 0         if (pstm_iszero(&s) == PS_FALSE)
3206             {
3207 0           break;
3208             }
3209             }
3210             }
3211 0           }
3212              
3213             /* If r or s has the high bit set, the ASN.1 encoding should include
3214             a leading 0x0 byte to prevent it from being "negative". */
3215 0           negative = (unsigned char *) r.dp;
3216 0 0         if (negative[rLen - 1] & 0x80)
3217             {
3218 0           rLen++;
3219 0           rflag = 1;
3220             }
3221 0           negative = (unsigned char *) s.dp;
3222 0 0         if (negative[sLen - 1] & 0x80) /* GOOD ONE */
3223             {
3224 0           sLen++;
3225 0           sflag = 1;
3226             }
3227 0           olen = 6 + rLen + sLen;
3228              
3229             /* Handle lengths longer than 128.. but still only handling up to 256 */
3230 0 0         if (olen - 3 >= 128)
3231             {
3232 0           olen++;
3233             }
3234              
3235             /* TLS uses a two byte length specifier. Others sometimes do not */
3236 0 0         if (includeSize)
3237             {
3238 0 0         if (olen + 2 > *siglen)
3239             {
3240 0           err = -1;
3241 0           goto errnokey;
3242             }
3243              
3244 0           *sig = olen >> 8 & 0xFF; sig++;
3245 0           *sig = olen & 0xFF; sig++;
3246             }
3247             else
3248             {
3249 0 0         if (olen > *siglen)
3250             {
3251 0           err = -1;
3252 0           goto errnokey;
3253             }
3254             }
3255              
3256 0           *sig = ASN_CONSTRUCTED | ASN_SEQUENCE; sig++;
3257              
3258 0 0         if ((olen - 3) >= 128)
3259             {
3260 0           *sig = 0x81; sig++; /* high bit to indicate 'long' and low for byte count */
3261 0           *sig = (olen & 0xFF) - 3; sig++;
3262 0           *siglen = 1;
3263             }
3264             else
3265             {
3266 0           *sig = (olen & 0xFF) - 2; sig++;
3267 0           *siglen = 0;
3268             }
3269 0           *sig = ASN_INTEGER; sig++;
3270 0           *sig = rLen & 0xFF; sig++;
3271 0 0         if (includeSize)
3272             {
3273 0           *siglen += 6;
3274             }
3275             else
3276             {
3277 0           *siglen += 4;
3278             }
3279 0 0         if (rflag)
3280             {
3281 0           *sig = 0x0; sig++;
3282             }
3283 0 0         if ((err = pstm_to_unsigned_bin(pool, &r, sig)) != PSTM_OKAY)
3284             {
3285 0           goto errnokey;
3286             }
3287 0           sig += rLen - rflag; /* Moved forward rflag already */
3288 0           *siglen += rLen;
3289 0           *sig = ASN_INTEGER; sig++;
3290 0           *sig = sLen & 0xFF; sig++;
3291 0 0         if (sflag)
3292             {
3293 0           *sig = 0x0; sig++;
3294             }
3295 0 0         if ((err = pstm_to_unsigned_bin(pool, &s, sig)) != PSTM_OKAY)
3296             {
3297 0           goto error;
3298             }
3299 0           *siglen += sLen + 2;
3300 0           err = PS_SUCCESS;
3301 0           goto errnokey;
3302              
3303             error:
3304 0           psEccClearKey(&pubKey);
3305             errnokey:
3306 0           pstm_clear(&s);
3307             LBL_R:
3308 0           pstm_clear(&r);
3309             LBL_E:
3310 0           pstm_clear(&e);
3311             LBL_P:
3312 0           pstm_clear(&p);
3313 0           return err;
3314             }
3315              
3316             #endif /* USE_MATRIX_ECC */
3317