1*f9fbec18Smcpowers /* 2*f9fbec18Smcpowers * ***** BEGIN LICENSE BLOCK ***** 3*f9fbec18Smcpowers * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4*f9fbec18Smcpowers * 5*f9fbec18Smcpowers * The contents of this file are subject to the Mozilla Public License Version 6*f9fbec18Smcpowers * 1.1 (the "License"); you may not use this file except in compliance with 7*f9fbec18Smcpowers * the License. You may obtain a copy of the License at 8*f9fbec18Smcpowers * http://www.mozilla.org/MPL/ 9*f9fbec18Smcpowers * 10*f9fbec18Smcpowers * Software distributed under the License is distributed on an "AS IS" basis, 11*f9fbec18Smcpowers * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12*f9fbec18Smcpowers * for the specific language governing rights and limitations under the 13*f9fbec18Smcpowers * License. 14*f9fbec18Smcpowers * 15*f9fbec18Smcpowers * The Original Code is the elliptic curve math library for prime field curves. 16*f9fbec18Smcpowers * 17*f9fbec18Smcpowers * The Initial Developer of the Original Code is 18*f9fbec18Smcpowers * Sun Microsystems, Inc. 19*f9fbec18Smcpowers * Portions created by the Initial Developer are Copyright (C) 2003 20*f9fbec18Smcpowers * the Initial Developer. All Rights Reserved. 21*f9fbec18Smcpowers * 22*f9fbec18Smcpowers * Contributor(s): 23*f9fbec18Smcpowers * Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories 24*f9fbec18Smcpowers * 25*f9fbec18Smcpowers * Alternatively, the contents of this file may be used under the terms of 26*f9fbec18Smcpowers * either the GNU General Public License Version 2 or later (the "GPL"), or 27*f9fbec18Smcpowers * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28*f9fbec18Smcpowers * in which case the provisions of the GPL or the LGPL are applicable instead 29*f9fbec18Smcpowers * of those above. If you wish to allow use of your version of this file only 30*f9fbec18Smcpowers * under the terms of either the GPL or the LGPL, and not to allow others to 31*f9fbec18Smcpowers * use your version of this file under the terms of the MPL, indicate your 32*f9fbec18Smcpowers * decision by deleting the provisions above and replace them with the notice 33*f9fbec18Smcpowers * and other provisions required by the GPL or the LGPL. If you do not delete 34*f9fbec18Smcpowers * the provisions above, a recipient may use your version of this file under 35*f9fbec18Smcpowers * the terms of any one of the MPL, the GPL or the LGPL. 36*f9fbec18Smcpowers * 37*f9fbec18Smcpowers * ***** END LICENSE BLOCK ***** */ 38*f9fbec18Smcpowers /* 39*f9fbec18Smcpowers * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 40*f9fbec18Smcpowers * Use is subject to license terms. 41*f9fbec18Smcpowers * 42*f9fbec18Smcpowers * Sun elects to use this software under the MPL license. 43*f9fbec18Smcpowers */ 44*f9fbec18Smcpowers 45*f9fbec18Smcpowers #pragma ident "%Z%%M% %I% %E% SMI" 46*f9fbec18Smcpowers 47*f9fbec18Smcpowers #include "ecp.h" 48*f9fbec18Smcpowers #include "ecl-priv.h" 49*f9fbec18Smcpowers #include "mplogic.h" 50*f9fbec18Smcpowers #ifndef _KERNEL 51*f9fbec18Smcpowers #include <stdlib.h> 52*f9fbec18Smcpowers #endif 53*f9fbec18Smcpowers 54*f9fbec18Smcpowers #define MAX_SCRATCH 6 55*f9fbec18Smcpowers 56*f9fbec18Smcpowers /* Computes R = 2P. Elliptic curve points P and R can be identical. Uses 57*f9fbec18Smcpowers * Modified Jacobian coordinates. 58*f9fbec18Smcpowers * 59*f9fbec18Smcpowers * Assumes input is already field-encoded using field_enc, and returns 60*f9fbec18Smcpowers * output that is still field-encoded. 61*f9fbec18Smcpowers * 62*f9fbec18Smcpowers */ 63*f9fbec18Smcpowers mp_err 64*f9fbec18Smcpowers ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz, 65*f9fbec18Smcpowers const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz, 66*f9fbec18Smcpowers mp_int *raz4, mp_int scratch[], const ECGroup *group) 67*f9fbec18Smcpowers { 68*f9fbec18Smcpowers mp_err res = MP_OKAY; 69*f9fbec18Smcpowers mp_int *t0, *t1, *M, *S; 70*f9fbec18Smcpowers 71*f9fbec18Smcpowers t0 = &scratch[0]; 72*f9fbec18Smcpowers t1 = &scratch[1]; 73*f9fbec18Smcpowers M = &scratch[2]; 74*f9fbec18Smcpowers S = &scratch[3]; 75*f9fbec18Smcpowers 76*f9fbec18Smcpowers #if MAX_SCRATCH < 4 77*f9fbec18Smcpowers #error "Scratch array defined too small " 78*f9fbec18Smcpowers #endif 79*f9fbec18Smcpowers 80*f9fbec18Smcpowers /* Check for point at infinity */ 81*f9fbec18Smcpowers if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { 82*f9fbec18Smcpowers /* Set r = pt at infinity by setting rz = 0 */ 83*f9fbec18Smcpowers 84*f9fbec18Smcpowers MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); 85*f9fbec18Smcpowers goto CLEANUP; 86*f9fbec18Smcpowers } 87*f9fbec18Smcpowers 88*f9fbec18Smcpowers /* M = 3 (px^2) + a*(pz^4) */ 89*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(px, t0, group->meth)); 90*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(t0, t0, M, group->meth)); 91*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(t0, M, t0, group->meth)); 92*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(t0, paz4, M, group->meth)); 93*f9fbec18Smcpowers 94*f9fbec18Smcpowers /* rz = 2 * py * pz */ 95*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(py, pz, S, group->meth)); 96*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth)); 97*f9fbec18Smcpowers 98*f9fbec18Smcpowers /* t0 = 2y^2 , t1 = 8y^4 */ 99*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth)); 100*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth)); 101*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth)); 102*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth)); 103*f9fbec18Smcpowers 104*f9fbec18Smcpowers /* S = 4 * px * py^2 = 2 * px * t0 */ 105*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(px, t0, S, group->meth)); 106*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(S, S, S, group->meth)); 107*f9fbec18Smcpowers 108*f9fbec18Smcpowers 109*f9fbec18Smcpowers /* rx = M^2 - 2S */ 110*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(M, rx, group->meth)); 111*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth)); 112*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth)); 113*f9fbec18Smcpowers 114*f9fbec18Smcpowers /* ry = M * (S - rx) - t1 */ 115*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(S, rx, S, group->meth)); 116*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth)); 117*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth)); 118*f9fbec18Smcpowers 119*f9fbec18Smcpowers /* ra*z^4 = 2*t1*(apz4) */ 120*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth)); 121*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth)); 122*f9fbec18Smcpowers 123*f9fbec18Smcpowers 124*f9fbec18Smcpowers CLEANUP: 125*f9fbec18Smcpowers return res; 126*f9fbec18Smcpowers } 127*f9fbec18Smcpowers 128*f9fbec18Smcpowers /* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is 129*f9fbec18Smcpowers * (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical. 130*f9fbec18Smcpowers * Uses mixed Modified_Jacobian-affine coordinates. Assumes input is 131*f9fbec18Smcpowers * already field-encoded using field_enc, and returns output that is still 132*f9fbec18Smcpowers * field-encoded. */ 133*f9fbec18Smcpowers mp_err 134*f9fbec18Smcpowers ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz, 135*f9fbec18Smcpowers const mp_int *paz4, const mp_int *qx, 136*f9fbec18Smcpowers const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz, 137*f9fbec18Smcpowers mp_int *raz4, mp_int scratch[], const ECGroup *group) 138*f9fbec18Smcpowers { 139*f9fbec18Smcpowers mp_err res = MP_OKAY; 140*f9fbec18Smcpowers mp_int *A, *B, *C, *D, *C2, *C3; 141*f9fbec18Smcpowers 142*f9fbec18Smcpowers A = &scratch[0]; 143*f9fbec18Smcpowers B = &scratch[1]; 144*f9fbec18Smcpowers C = &scratch[2]; 145*f9fbec18Smcpowers D = &scratch[3]; 146*f9fbec18Smcpowers C2 = &scratch[4]; 147*f9fbec18Smcpowers C3 = &scratch[5]; 148*f9fbec18Smcpowers 149*f9fbec18Smcpowers #if MAX_SCRATCH < 6 150*f9fbec18Smcpowers #error "Scratch array defined too small " 151*f9fbec18Smcpowers #endif 152*f9fbec18Smcpowers 153*f9fbec18Smcpowers /* If either P or Q is the point at infinity, then return the other 154*f9fbec18Smcpowers * point */ 155*f9fbec18Smcpowers if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { 156*f9fbec18Smcpowers MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group)); 157*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth)); 158*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth)); 159*f9fbec18Smcpowers MP_CHECKOK(group->meth-> 160*f9fbec18Smcpowers field_mul(raz4, &group->curvea, raz4, group->meth)); 161*f9fbec18Smcpowers goto CLEANUP; 162*f9fbec18Smcpowers } 163*f9fbec18Smcpowers if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) { 164*f9fbec18Smcpowers MP_CHECKOK(mp_copy(px, rx)); 165*f9fbec18Smcpowers MP_CHECKOK(mp_copy(py, ry)); 166*f9fbec18Smcpowers MP_CHECKOK(mp_copy(pz, rz)); 167*f9fbec18Smcpowers MP_CHECKOK(mp_copy(paz4, raz4)); 168*f9fbec18Smcpowers goto CLEANUP; 169*f9fbec18Smcpowers } 170*f9fbec18Smcpowers 171*f9fbec18Smcpowers /* A = qx * pz^2, B = qy * pz^3 */ 172*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth)); 173*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth)); 174*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth)); 175*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth)); 176*f9fbec18Smcpowers 177*f9fbec18Smcpowers /* C = A - px, D = B - py */ 178*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth)); 179*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth)); 180*f9fbec18Smcpowers 181*f9fbec18Smcpowers /* C2 = C^2, C3 = C^3 */ 182*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth)); 183*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth)); 184*f9fbec18Smcpowers 185*f9fbec18Smcpowers /* rz = pz * C */ 186*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth)); 187*f9fbec18Smcpowers 188*f9fbec18Smcpowers /* C = px * C^2 */ 189*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth)); 190*f9fbec18Smcpowers /* A = D^2 */ 191*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(D, A, group->meth)); 192*f9fbec18Smcpowers 193*f9fbec18Smcpowers /* rx = D^2 - (C^3 + 2 * (px * C^2)) */ 194*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth)); 195*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth)); 196*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth)); 197*f9fbec18Smcpowers 198*f9fbec18Smcpowers /* C3 = py * C^3 */ 199*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth)); 200*f9fbec18Smcpowers 201*f9fbec18Smcpowers /* ry = D * (px * C^2 - rx) - py * C^3 */ 202*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth)); 203*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth)); 204*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth)); 205*f9fbec18Smcpowers 206*f9fbec18Smcpowers /* raz4 = a * rz^4 */ 207*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth)); 208*f9fbec18Smcpowers MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth)); 209*f9fbec18Smcpowers MP_CHECKOK(group->meth-> 210*f9fbec18Smcpowers field_mul(raz4, &group->curvea, raz4, group->meth)); 211*f9fbec18Smcpowers CLEANUP: 212*f9fbec18Smcpowers return res; 213*f9fbec18Smcpowers } 214*f9fbec18Smcpowers 215*f9fbec18Smcpowers /* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic 216*f9fbec18Smcpowers * curve points P and R can be identical. Uses mixed Modified-Jacobian 217*f9fbec18Smcpowers * co-ordinates for doubling and Chudnovsky Jacobian coordinates for 218*f9fbec18Smcpowers * additions. Assumes input is already field-encoded using field_enc, and 219*f9fbec18Smcpowers * returns output that is still field-encoded. Uses 5-bit window NAF 220*f9fbec18Smcpowers * method (algorithm 11) for scalar-point multiplication from Brown, 221*f9fbec18Smcpowers * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic 222*f9fbec18Smcpowers * Curves Over Prime Fields. */ 223*f9fbec18Smcpowers mp_err 224*f9fbec18Smcpowers ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, 225*f9fbec18Smcpowers mp_int *rx, mp_int *ry, const ECGroup *group) 226*f9fbec18Smcpowers { 227*f9fbec18Smcpowers mp_err res = MP_OKAY; 228*f9fbec18Smcpowers mp_int precomp[16][2], rz, tpx, tpy; 229*f9fbec18Smcpowers mp_int raz4; 230*f9fbec18Smcpowers mp_int scratch[MAX_SCRATCH]; 231*f9fbec18Smcpowers signed char *naf = NULL; 232*f9fbec18Smcpowers int i, orderBitSize; 233*f9fbec18Smcpowers 234*f9fbec18Smcpowers MP_DIGITS(&rz) = 0; 235*f9fbec18Smcpowers MP_DIGITS(&raz4) = 0; 236*f9fbec18Smcpowers MP_DIGITS(&tpx) = 0; 237*f9fbec18Smcpowers MP_DIGITS(&tpy) = 0; 238*f9fbec18Smcpowers for (i = 0; i < 16; i++) { 239*f9fbec18Smcpowers MP_DIGITS(&precomp[i][0]) = 0; 240*f9fbec18Smcpowers MP_DIGITS(&precomp[i][1]) = 0; 241*f9fbec18Smcpowers } 242*f9fbec18Smcpowers for (i = 0; i < MAX_SCRATCH; i++) { 243*f9fbec18Smcpowers MP_DIGITS(&scratch[i]) = 0; 244*f9fbec18Smcpowers } 245*f9fbec18Smcpowers 246*f9fbec18Smcpowers ARGCHK(group != NULL, MP_BADARG); 247*f9fbec18Smcpowers ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); 248*f9fbec18Smcpowers 249*f9fbec18Smcpowers /* initialize precomputation table */ 250*f9fbec18Smcpowers MP_CHECKOK(mp_init(&tpx, FLAG(n))); 251*f9fbec18Smcpowers MP_CHECKOK(mp_init(&tpy, FLAG(n)));; 252*f9fbec18Smcpowers MP_CHECKOK(mp_init(&rz, FLAG(n))); 253*f9fbec18Smcpowers MP_CHECKOK(mp_init(&raz4, FLAG(n))); 254*f9fbec18Smcpowers 255*f9fbec18Smcpowers for (i = 0; i < 16; i++) { 256*f9fbec18Smcpowers MP_CHECKOK(mp_init(&precomp[i][0], FLAG(n))); 257*f9fbec18Smcpowers MP_CHECKOK(mp_init(&precomp[i][1], FLAG(n))); 258*f9fbec18Smcpowers } 259*f9fbec18Smcpowers for (i = 0; i < MAX_SCRATCH; i++) { 260*f9fbec18Smcpowers MP_CHECKOK(mp_init(&scratch[i], FLAG(n))); 261*f9fbec18Smcpowers } 262*f9fbec18Smcpowers 263*f9fbec18Smcpowers /* Set out[8] = P */ 264*f9fbec18Smcpowers MP_CHECKOK(mp_copy(px, &precomp[8][0])); 265*f9fbec18Smcpowers MP_CHECKOK(mp_copy(py, &precomp[8][1])); 266*f9fbec18Smcpowers 267*f9fbec18Smcpowers /* Set (tpx, tpy) = 2P */ 268*f9fbec18Smcpowers MP_CHECKOK(group-> 269*f9fbec18Smcpowers point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy, 270*f9fbec18Smcpowers group)); 271*f9fbec18Smcpowers 272*f9fbec18Smcpowers /* Set 3P, 5P, ..., 15P */ 273*f9fbec18Smcpowers for (i = 8; i < 15; i++) { 274*f9fbec18Smcpowers MP_CHECKOK(group-> 275*f9fbec18Smcpowers point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy, 276*f9fbec18Smcpowers &precomp[i + 1][0], &precomp[i + 1][1], 277*f9fbec18Smcpowers group)); 278*f9fbec18Smcpowers } 279*f9fbec18Smcpowers 280*f9fbec18Smcpowers /* Set -15P, -13P, ..., -P */ 281*f9fbec18Smcpowers for (i = 0; i < 8; i++) { 282*f9fbec18Smcpowers MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0])); 283*f9fbec18Smcpowers MP_CHECKOK(group->meth-> 284*f9fbec18Smcpowers field_neg(&precomp[15 - i][1], &precomp[i][1], 285*f9fbec18Smcpowers group->meth)); 286*f9fbec18Smcpowers } 287*f9fbec18Smcpowers 288*f9fbec18Smcpowers /* R = inf */ 289*f9fbec18Smcpowers MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz)); 290*f9fbec18Smcpowers 291*f9fbec18Smcpowers orderBitSize = mpl_significant_bits(&group->order); 292*f9fbec18Smcpowers 293*f9fbec18Smcpowers /* Allocate memory for NAF */ 294*f9fbec18Smcpowers #ifdef _KERNEL 295*f9fbec18Smcpowers naf = (signed char *) kmem_alloc((orderBitSize + 1), FLAG(n)); 296*f9fbec18Smcpowers #else 297*f9fbec18Smcpowers naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1)); 298*f9fbec18Smcpowers if (naf == NULL) { 299*f9fbec18Smcpowers res = MP_MEM; 300*f9fbec18Smcpowers goto CLEANUP; 301*f9fbec18Smcpowers } 302*f9fbec18Smcpowers #endif 303*f9fbec18Smcpowers 304*f9fbec18Smcpowers /* Compute 5NAF */ 305*f9fbec18Smcpowers ec_compute_wNAF(naf, orderBitSize, n, 5); 306*f9fbec18Smcpowers 307*f9fbec18Smcpowers /* wNAF method */ 308*f9fbec18Smcpowers for (i = orderBitSize; i >= 0; i--) { 309*f9fbec18Smcpowers /* R = 2R */ 310*f9fbec18Smcpowers ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz, 311*f9fbec18Smcpowers &raz4, scratch, group); 312*f9fbec18Smcpowers if (naf[i] != 0) { 313*f9fbec18Smcpowers ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4, 314*f9fbec18Smcpowers &precomp[(naf[i] + 15) / 2][0], 315*f9fbec18Smcpowers &precomp[(naf[i] + 15) / 2][1], rx, ry, 316*f9fbec18Smcpowers &rz, &raz4, scratch, group); 317*f9fbec18Smcpowers } 318*f9fbec18Smcpowers } 319*f9fbec18Smcpowers 320*f9fbec18Smcpowers /* convert result S to affine coordinates */ 321*f9fbec18Smcpowers MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); 322*f9fbec18Smcpowers 323*f9fbec18Smcpowers CLEANUP: 324*f9fbec18Smcpowers for (i = 0; i < MAX_SCRATCH; i++) { 325*f9fbec18Smcpowers mp_clear(&scratch[i]); 326*f9fbec18Smcpowers } 327*f9fbec18Smcpowers for (i = 0; i < 16; i++) { 328*f9fbec18Smcpowers mp_clear(&precomp[i][0]); 329*f9fbec18Smcpowers mp_clear(&precomp[i][1]); 330*f9fbec18Smcpowers } 331*f9fbec18Smcpowers mp_clear(&tpx); 332*f9fbec18Smcpowers mp_clear(&tpy); 333*f9fbec18Smcpowers mp_clear(&rz); 334*f9fbec18Smcpowers mp_clear(&raz4); 335*f9fbec18Smcpowers #ifdef _KERNEL 336*f9fbec18Smcpowers kmem_free(naf, (orderBitSize + 1)); 337*f9fbec18Smcpowers #else 338*f9fbec18Smcpowers free(naf); 339*f9fbec18Smcpowers #endif 340*f9fbec18Smcpowers return res; 341*f9fbec18Smcpowers } 342