OLD | NEW |
(Empty) | |
| 1 diff --git a/net/third_party/nss/ssl/mpi/logtab.h b/net/third_party/nss/ssl/mpi/
logtab.h |
| 2 new file mode 100644 |
| 3 index 0000000..41badfc |
| 4 --- /dev/null |
| 5 +++ b/net/third_party/nss/ssl/mpi/logtab.h |
| 6 @@ -0,0 +1,62 @@ |
| 7 +/* |
| 8 + * logtab.h |
| 9 + * |
| 10 + * Arbitrary precision integer arithmetic library |
| 11 + * |
| 12 + * ***** BEGIN LICENSE BLOCK ***** |
| 13 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 14 + * |
| 15 + * The contents of this file are subject to the Mozilla Public License Version |
| 16 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 17 + * the License. You may obtain a copy of the License at |
| 18 + * http://www.mozilla.org/MPL/ |
| 19 + * |
| 20 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 21 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 22 + * for the specific language governing rights and limitations under the |
| 23 + * License. |
| 24 + * |
| 25 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 26 + * |
| 27 + * The Initial Developer of the Original Code is |
| 28 + * Michael J. Fromberger. |
| 29 + * Portions created by the Initial Developer are Copyright (C) 1998 |
| 30 + * the Initial Developer. All Rights Reserved. |
| 31 + * |
| 32 + * Contributor(s): |
| 33 + * |
| 34 + * Alternatively, the contents of this file may be used under the terms of |
| 35 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 36 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 37 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 38 + * of those above. If you wish to allow use of your version of this file only |
| 39 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 40 + * use your version of this file under the terms of the MPL, indicate your |
| 41 + * decision by deleting the provisions above and replace them with the notice |
| 42 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 43 + * the provisions above, a recipient may use your version of this file under |
| 44 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 45 + * |
| 46 + * ***** END LICENSE BLOCK ***** */ |
| 47 +/* $Id: logtab.h,v 1.5 2004/04/27 23:04:36 gerv%gerv.net Exp $ */ |
| 48 + |
| 49 +const float s_logv_2[] = { |
| 50 + 0.000000000f, 0.000000000f, 1.000000000f, 0.630929754f, /* 0 1 2 3 */ |
| 51 + 0.500000000f, 0.430676558f, 0.386852807f, 0.356207187f, /* 4 5 6 7 */ |
| 52 + 0.333333333f, 0.315464877f, 0.301029996f, 0.289064826f, /* 8 9 10 11 */ |
| 53 + 0.278942946f, 0.270238154f, 0.262649535f, 0.255958025f, /* 12 13 14 15 */ |
| 54 + 0.250000000f, 0.244650542f, 0.239812467f, 0.235408913f, /* 16 17 18 19 */ |
| 55 + 0.231378213f, 0.227670249f, 0.224243824f, 0.221064729f, /* 20 21 22 23 */ |
| 56 + 0.218104292f, 0.215338279f, 0.212746054f, 0.210309918f, /* 24 25 26 27 */ |
| 57 + 0.208014598f, 0.205846832f, 0.203795047f, 0.201849087f, /* 28 29 30 31 */ |
| 58 + 0.200000000f, 0.198239863f, 0.196561632f, 0.194959022f, /* 32 33 34 35 */ |
| 59 + 0.193426404f, 0.191958720f, 0.190551412f, 0.189200360f, /* 36 37 38 39 */ |
| 60 + 0.187901825f, 0.186652411f, 0.185449023f, 0.184288833f, /* 40 41 42 43 */ |
| 61 + 0.183169251f, 0.182087900f, 0.181042597f, 0.180031327f, /* 44 45 46 47 */ |
| 62 + 0.179052232f, 0.178103594f, 0.177183820f, 0.176291434f, /* 48 49 50 51 */ |
| 63 + 0.175425064f, 0.174583430f, 0.173765343f, 0.172969690f, /* 52 53 54 55 */ |
| 64 + 0.172195434f, 0.171441601f, 0.170707280f, 0.169991616f, /* 56 57 58 59 */ |
| 65 + 0.169293808f, 0.168613099f, 0.167948779f, 0.167300179f, /* 60 61 62 63 */ |
| 66 + 0.166666667f |
| 67 +}; |
| 68 + |
| 69 diff --git a/net/third_party/nss/ssl/mpi/mpcpucache.c b/net/third_party/nss/ssl/
mpi/mpcpucache.c |
| 70 new file mode 100644 |
| 71 index 0000000..6efa072 |
| 72 --- /dev/null |
| 73 +++ b/net/third_party/nss/ssl/mpi/mpcpucache.c |
| 74 @@ -0,0 +1,838 @@ |
| 75 +/* ***** BEGIN LICENSE BLOCK ***** |
| 76 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 77 + * |
| 78 + * The contents of this file are subject to the Mozilla Public License Version |
| 79 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 80 + * the License. You may obtain a copy of the License at |
| 81 + * http://www.mozilla.org/MPL/ |
| 82 + * |
| 83 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 84 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 85 + * for the specific language governing rights and limitations under the |
| 86 + * License. |
| 87 + * |
| 88 + * The Original Code is the Netscape security libraries. |
| 89 + * |
| 90 + * The Initial Developer of the Original Code is |
| 91 + * Red Hat, Inc |
| 92 + * Portions created by the Initial Developer are Copyright (C) 2005 |
| 93 + * the Initial Developer. All Rights Reserved. |
| 94 + * |
| 95 + * Contributor(s): |
| 96 + * Robert Relyea <rrelyea@redhat.com> |
| 97 + * |
| 98 + * Alternatively, the contents of this file may be used under the terms of |
| 99 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 100 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 101 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 102 + * of those above. If you wish to allow use of your version of this file only |
| 103 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 104 + * use your version of this file under the terms of the MPL, indicate your |
| 105 + * decision by deleting the provisions above and replace them with the notice |
| 106 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 107 + * the provisions above, a recipient may use your version of this file under |
| 108 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 109 + * |
| 110 + * ***** END LICENSE BLOCK ***** */ |
| 111 + |
| 112 +#include "mpi.h" |
| 113 + |
| 114 +/* |
| 115 + * This file implements a single function: s_mpi_getProcessorLineSize(); |
| 116 + * s_mpi_getProcessorLineSize() returns the size in bytes of the cache line |
| 117 + * if a cache exists, or zero if there is no cache. If more than one |
| 118 + * cache line exists, it should return the smallest line size (which is |
| 119 + * usually the L1 cache). |
| 120 + * |
| 121 + * mp_modexp uses this information to make sure that private key information |
| 122 + * isn't being leaked through the cache. |
| 123 + * |
| 124 + * Currently the file returns good data for most modern x86 processors, and |
| 125 + * reasonable data on 64-bit ppc processors. All other processors are assumed |
| 126 + * to have a cache line size of 32 bytes unless modified by target.mk. |
| 127 + * |
| 128 + */ |
| 129 + |
| 130 +#if defined(i386) || defined(__i386) || defined(__X86__) || defined (_M_IX86) |
| defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) |
| 131 +/* X86 processors have special instructions that tell us about the cache */ |
| 132 +#include "string.h" |
| 133 + |
| 134 +#if defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) |
| 135 +#define AMD_64 1 |
| 136 +#endif |
| 137 + |
| 138 +/* Generic CPUID function */ |
| 139 +#if defined(AMD_64) |
| 140 + |
| 141 +#if defined(__GNUC__) |
| 142 + |
| 143 +void freebl_cpuid(unsigned long op, unsigned long *eax, |
| 144 + unsigned long *ebx, unsigned long *ecx, |
| 145 + unsigned long *edx) |
| 146 +{ |
| 147 + __asm__("cpuid\n\t" |
| 148 + : "=a" (*eax), |
| 149 + "=b" (*ebx), |
| 150 + "=c" (*ecx), |
| 151 + "=d" (*edx) |
| 152 + : "0" (op)); |
| 153 +} |
| 154 + |
| 155 +#elif defined(_MSC_VER) |
| 156 + |
| 157 +#include <intrin.h> |
| 158 + |
| 159 +void freebl_cpuid(unsigned long op, unsigned long *eax, |
| 160 + unsigned long *ebx, unsigned long *ecx, |
| 161 + unsigned long *edx) |
| 162 +{ |
| 163 + int intrinsic_out[4]; |
| 164 + |
| 165 + __cpuid(intrinsic_out, op); |
| 166 + *eax = intrinsic_out[0]; |
| 167 + *ebx = intrinsic_out[1]; |
| 168 + *ecx = intrinsic_out[2]; |
| 169 + *edx = intrinsic_out[3]; |
| 170 +} |
| 171 + |
| 172 +#endif |
| 173 + |
| 174 +#else /* !defined(AMD_64) */ |
| 175 + |
| 176 +/* x86 */ |
| 177 + |
| 178 +#if defined(__GNUC__) |
| 179 +void freebl_cpuid(unsigned long op, unsigned long *eax, |
| 180 + unsigned long *ebx, unsigned long *ecx, |
| 181 + unsigned long *edx) |
| 182 +{ |
| 183 +/* sigh GCC isn't smart enough to save the ebx PIC register on it's own |
| 184 + * in this case, so do it by hand. */ |
| 185 + __asm__("pushl %%ebx\n\t" |
| 186 + "cpuid\n\t" |
| 187 + "mov %%ebx,%1\n\t" |
| 188 + "popl %%ebx\n\t" |
| 189 + : "=a" (*eax), |
| 190 + "=r" (*ebx), |
| 191 + "=c" (*ecx), |
| 192 + "=d" (*edx) |
| 193 + : "0" (op)); |
| 194 +} |
| 195 + |
| 196 +/* |
| 197 + * try flipping a processor flag to determine CPU type |
| 198 + */ |
| 199 +static unsigned long changeFlag(unsigned long flag) |
| 200 +{ |
| 201 + unsigned long changedFlags, originalFlags; |
| 202 + __asm__("pushfl\n\t" /* get the flags */ |
| 203 + "popl %0\n\t" |
| 204 + "movl %0,%1\n\t" /* save the original flags */ |
| 205 + "xorl %2,%0\n\t" /* flip the bit */ |
| 206 + "pushl %0\n\t" /* set the flags */ |
| 207 + "popfl\n\t" |
| 208 + "pushfl\n\t" /* get the flags again (for return) */ |
| 209 + "popl %0\n\t" |
| 210 + "pushl %1\n\t" /* restore the original flags */ |
| 211 + "popfl\n\t" |
| 212 + : "=r" (changedFlags), |
| 213 + "=r" (originalFlags), |
| 214 + "=r" (flag) |
| 215 + : "2" (flag)); |
| 216 + return changedFlags ^ originalFlags; |
| 217 +} |
| 218 + |
| 219 +#elif defined(_MSC_VER) |
| 220 + |
| 221 +/* |
| 222 + * windows versions of the above assembler |
| 223 + */ |
| 224 +#define wcpuid __asm __emit 0fh __asm __emit 0a2h |
| 225 +void freebl_cpuid(unsigned long op, unsigned long *Reax, |
| 226 + unsigned long *Rebx, unsigned long *Recx, unsigned long *Redx) |
| 227 +{ |
| 228 + unsigned long Leax, Lebx, Lecx, Ledx; |
| 229 + __asm { |
| 230 + pushad |
| 231 + mov eax,op |
| 232 + wcpuid |
| 233 + mov Leax,eax |
| 234 + mov Lebx,ebx |
| 235 + mov Lecx,ecx |
| 236 + mov Ledx,edx |
| 237 + popad |
| 238 + } |
| 239 + *Reax = Leax; |
| 240 + *Rebx = Lebx; |
| 241 + *Recx = Lecx; |
| 242 + *Redx = Ledx; |
| 243 +} |
| 244 + |
| 245 +static unsigned long changeFlag(unsigned long flag) |
| 246 +{ |
| 247 + unsigned long changedFlags, originalFlags; |
| 248 + __asm { |
| 249 + push eax |
| 250 + push ebx |
| 251 + pushfd /* get the flags */ |
| 252 + pop eax |
| 253 + push eax /* save the flags on the stack */ |
| 254 + mov originalFlags,eax /* save the original flags */ |
| 255 + mov ebx,flag |
| 256 + xor eax,ebx /* flip the bit */ |
| 257 + push eax /* set the flags */ |
| 258 + popfd |
| 259 + pushfd /* get the flags again (for return) */ |
| 260 + pop eax |
| 261 + popfd /* restore the original flags */ |
| 262 + mov changedFlags,eax |
| 263 + pop ebx |
| 264 + pop eax |
| 265 + } |
| 266 + return changedFlags ^ originalFlags; |
| 267 +} |
| 268 +#endif |
| 269 + |
| 270 +#endif |
| 271 + |
| 272 +#if !defined(AMD_64) |
| 273 +#define AC_FLAG 0x40000 |
| 274 +#define ID_FLAG 0x200000 |
| 275 + |
| 276 +/* 386 processors can't flip the AC_FLAG, intel AP Note AP-485 */ |
| 277 +static int is386() |
| 278 +{ |
| 279 + return changeFlag(AC_FLAG) == 0; |
| 280 +} |
| 281 + |
| 282 +/* 486 processors can't flip the ID_FLAG, intel AP Note AP-485 */ |
| 283 +static int is486() |
| 284 +{ |
| 285 + return changeFlag(ID_FLAG) == 0; |
| 286 +} |
| 287 +#endif |
| 288 + |
| 289 + |
| 290 +/* |
| 291 + * table for Intel Cache. |
| 292 + * See Intel Application Note AP-485 for more information |
| 293 + */ |
| 294 + |
| 295 +typedef unsigned char CacheTypeEntry; |
| 296 + |
| 297 +typedef enum { |
| 298 + Cache_NONE = 0, |
| 299 + Cache_UNKNOWN = 1, |
| 300 + Cache_TLB = 2, |
| 301 + Cache_TLBi = 3, |
| 302 + Cache_TLBd = 4, |
| 303 + Cache_Trace = 5, |
| 304 + Cache_L1 = 6, |
| 305 + Cache_L1i = 7, |
| 306 + Cache_L1d = 8, |
| 307 + Cache_L2 = 9 , |
| 308 + Cache_L2i = 10 , |
| 309 + Cache_L2d = 11 , |
| 310 + Cache_L3 = 12 , |
| 311 + Cache_L3i = 13, |
| 312 + Cache_L3d = 14 |
| 313 +} CacheType; |
| 314 + |
| 315 +struct _cache { |
| 316 + CacheTypeEntry type; |
| 317 + unsigned char lineSize; |
| 318 +}; |
| 319 +static const struct _cache CacheMap[256] = { |
| 320 +/* 00 */ {Cache_NONE, 0 }, |
| 321 +/* 01 */ {Cache_TLBi, 0 }, |
| 322 +/* 02 */ {Cache_TLBi, 0 }, |
| 323 +/* 03 */ {Cache_TLBd, 0 }, |
| 324 +/* 04 */ {Cache_TLBd, }, |
| 325 +/* 05 */ {Cache_UNKNOWN, 0 }, |
| 326 +/* 06 */ {Cache_L1i, 32 }, |
| 327 +/* 07 */ {Cache_UNKNOWN, 0 }, |
| 328 +/* 08 */ {Cache_L1i, 32 }, |
| 329 +/* 09 */ {Cache_UNKNOWN, 0 }, |
| 330 +/* 0a */ {Cache_L1d, 32 }, |
| 331 +/* 0b */ {Cache_UNKNOWN, 0 }, |
| 332 +/* 0c */ {Cache_L1d, 32 }, |
| 333 +/* 0d */ {Cache_UNKNOWN, 0 }, |
| 334 +/* 0e */ {Cache_UNKNOWN, 0 }, |
| 335 +/* 0f */ {Cache_UNKNOWN, 0 }, |
| 336 +/* 10 */ {Cache_UNKNOWN, 0 }, |
| 337 +/* 11 */ {Cache_UNKNOWN, 0 }, |
| 338 +/* 12 */ {Cache_UNKNOWN, 0 }, |
| 339 +/* 13 */ {Cache_UNKNOWN, 0 }, |
| 340 +/* 14 */ {Cache_UNKNOWN, 0 }, |
| 341 +/* 15 */ {Cache_UNKNOWN, 0 }, |
| 342 +/* 16 */ {Cache_UNKNOWN, 0 }, |
| 343 +/* 17 */ {Cache_UNKNOWN, 0 }, |
| 344 +/* 18 */ {Cache_UNKNOWN, 0 }, |
| 345 +/* 19 */ {Cache_UNKNOWN, 0 }, |
| 346 +/* 1a */ {Cache_UNKNOWN, 0 }, |
| 347 +/* 1b */ {Cache_UNKNOWN, 0 }, |
| 348 +/* 1c */ {Cache_UNKNOWN, 0 }, |
| 349 +/* 1d */ {Cache_UNKNOWN, 0 }, |
| 350 +/* 1e */ {Cache_UNKNOWN, 0 }, |
| 351 +/* 1f */ {Cache_UNKNOWN, 0 }, |
| 352 +/* 20 */ {Cache_UNKNOWN, 0 }, |
| 353 +/* 21 */ {Cache_UNKNOWN, 0 }, |
| 354 +/* 22 */ {Cache_L3, 64 }, |
| 355 +/* 23 */ {Cache_L3, 64 }, |
| 356 +/* 24 */ {Cache_UNKNOWN, 0 }, |
| 357 +/* 25 */ {Cache_L3, 64 }, |
| 358 +/* 26 */ {Cache_UNKNOWN, 0 }, |
| 359 +/* 27 */ {Cache_UNKNOWN, 0 }, |
| 360 +/* 28 */ {Cache_UNKNOWN, 0 }, |
| 361 +/* 29 */ {Cache_L3, 64 }, |
| 362 +/* 2a */ {Cache_UNKNOWN, 0 }, |
| 363 +/* 2b */ {Cache_UNKNOWN, 0 }, |
| 364 +/* 2c */ {Cache_L1d, 64 }, |
| 365 +/* 2d */ {Cache_UNKNOWN, 0 }, |
| 366 +/* 2e */ {Cache_UNKNOWN, 0 }, |
| 367 +/* 2f */ {Cache_UNKNOWN, 0 }, |
| 368 +/* 30 */ {Cache_L1i, 64 }, |
| 369 +/* 31 */ {Cache_UNKNOWN, 0 }, |
| 370 +/* 32 */ {Cache_UNKNOWN, 0 }, |
| 371 +/* 33 */ {Cache_UNKNOWN, 0 }, |
| 372 +/* 34 */ {Cache_UNKNOWN, 0 }, |
| 373 +/* 35 */ {Cache_UNKNOWN, 0 }, |
| 374 +/* 36 */ {Cache_UNKNOWN, 0 }, |
| 375 +/* 37 */ {Cache_UNKNOWN, 0 }, |
| 376 +/* 38 */ {Cache_UNKNOWN, 0 }, |
| 377 +/* 39 */ {Cache_L2, 64 }, |
| 378 +/* 3a */ {Cache_UNKNOWN, 0 }, |
| 379 +/* 3b */ {Cache_L2, 64 }, |
| 380 +/* 3c */ {Cache_L2, 64 }, |
| 381 +/* 3d */ {Cache_UNKNOWN, 0 }, |
| 382 +/* 3e */ {Cache_UNKNOWN, 0 }, |
| 383 +/* 3f */ {Cache_UNKNOWN, 0 }, |
| 384 +/* 40 */ {Cache_L2, 0 }, |
| 385 +/* 41 */ {Cache_L2, 32 }, |
| 386 +/* 42 */ {Cache_L2, 32 }, |
| 387 +/* 43 */ {Cache_L2, 32 }, |
| 388 +/* 44 */ {Cache_L2, 32 }, |
| 389 +/* 45 */ {Cache_L2, 32 }, |
| 390 +/* 46 */ {Cache_UNKNOWN, 0 }, |
| 391 +/* 47 */ {Cache_UNKNOWN, 0 }, |
| 392 +/* 48 */ {Cache_UNKNOWN, 0 }, |
| 393 +/* 49 */ {Cache_UNKNOWN, 0 }, |
| 394 +/* 4a */ {Cache_UNKNOWN, 0 }, |
| 395 +/* 4b */ {Cache_UNKNOWN, 0 }, |
| 396 +/* 4c */ {Cache_UNKNOWN, 0 }, |
| 397 +/* 4d */ {Cache_UNKNOWN, 0 }, |
| 398 +/* 4e */ {Cache_UNKNOWN, 0 }, |
| 399 +/* 4f */ {Cache_UNKNOWN, 0 }, |
| 400 +/* 50 */ {Cache_TLBi, 0 }, |
| 401 +/* 51 */ {Cache_TLBi, 0 }, |
| 402 +/* 52 */ {Cache_TLBi, 0 }, |
| 403 +/* 53 */ {Cache_UNKNOWN, 0 }, |
| 404 +/* 54 */ {Cache_UNKNOWN, 0 }, |
| 405 +/* 55 */ {Cache_UNKNOWN, 0 }, |
| 406 +/* 56 */ {Cache_UNKNOWN, 0 }, |
| 407 +/* 57 */ {Cache_UNKNOWN, 0 }, |
| 408 +/* 58 */ {Cache_UNKNOWN, 0 }, |
| 409 +/* 59 */ {Cache_UNKNOWN, 0 }, |
| 410 +/* 5a */ {Cache_UNKNOWN, 0 }, |
| 411 +/* 5b */ {Cache_TLBd, 0 }, |
| 412 +/* 5c */ {Cache_TLBd, 0 }, |
| 413 +/* 5d */ {Cache_TLBd, 0 }, |
| 414 +/* 5e */ {Cache_UNKNOWN, 0 }, |
| 415 +/* 5f */ {Cache_UNKNOWN, 0 }, |
| 416 +/* 60 */ {Cache_UNKNOWN, 0 }, |
| 417 +/* 61 */ {Cache_UNKNOWN, 0 }, |
| 418 +/* 62 */ {Cache_UNKNOWN, 0 }, |
| 419 +/* 63 */ {Cache_UNKNOWN, 0 }, |
| 420 +/* 64 */ {Cache_UNKNOWN, 0 }, |
| 421 +/* 65 */ {Cache_UNKNOWN, 0 }, |
| 422 +/* 66 */ {Cache_L1d, 64 }, |
| 423 +/* 67 */ {Cache_L1d, 64 }, |
| 424 +/* 68 */ {Cache_L1d, 64 }, |
| 425 +/* 69 */ {Cache_UNKNOWN, 0 }, |
| 426 +/* 6a */ {Cache_UNKNOWN, 0 }, |
| 427 +/* 6b */ {Cache_UNKNOWN, 0 }, |
| 428 +/* 6c */ {Cache_UNKNOWN, 0 }, |
| 429 +/* 6d */ {Cache_UNKNOWN, 0 }, |
| 430 +/* 6e */ {Cache_UNKNOWN, 0 }, |
| 431 +/* 6f */ {Cache_UNKNOWN, 0 }, |
| 432 +/* 70 */ {Cache_Trace, 1 }, |
| 433 +/* 71 */ {Cache_Trace, 1 }, |
| 434 +/* 72 */ {Cache_Trace, 1 }, |
| 435 +/* 73 */ {Cache_UNKNOWN, 0 }, |
| 436 +/* 74 */ {Cache_UNKNOWN, 0 }, |
| 437 +/* 75 */ {Cache_UNKNOWN, 0 }, |
| 438 +/* 76 */ {Cache_UNKNOWN, 0 }, |
| 439 +/* 77 */ {Cache_UNKNOWN, 0 }, |
| 440 +/* 78 */ {Cache_UNKNOWN, 0 }, |
| 441 +/* 79 */ {Cache_L2, 64 }, |
| 442 +/* 7a */ {Cache_L2, 64 }, |
| 443 +/* 7b */ {Cache_L2, 64 }, |
| 444 +/* 7c */ {Cache_L2, 64 }, |
| 445 +/* 7d */ {Cache_UNKNOWN, 0 }, |
| 446 +/* 7e */ {Cache_UNKNOWN, 0 }, |
| 447 +/* 7f */ {Cache_UNKNOWN, 0 }, |
| 448 +/* 80 */ {Cache_UNKNOWN, 0 }, |
| 449 +/* 81 */ {Cache_UNKNOWN, 0 }, |
| 450 +/* 82 */ {Cache_L2, 32 }, |
| 451 +/* 83 */ {Cache_L2, 32 }, |
| 452 +/* 84 */ {Cache_L2, 32 }, |
| 453 +/* 85 */ {Cache_L2, 32 }, |
| 454 +/* 86 */ {Cache_L2, 64 }, |
| 455 +/* 87 */ {Cache_L2, 64 }, |
| 456 +/* 88 */ {Cache_UNKNOWN, 0 }, |
| 457 +/* 89 */ {Cache_UNKNOWN, 0 }, |
| 458 +/* 8a */ {Cache_UNKNOWN, 0 }, |
| 459 +/* 8b */ {Cache_UNKNOWN, 0 }, |
| 460 +/* 8c */ {Cache_UNKNOWN, 0 }, |
| 461 +/* 8d */ {Cache_UNKNOWN, 0 }, |
| 462 +/* 8e */ {Cache_UNKNOWN, 0 }, |
| 463 +/* 8f */ {Cache_UNKNOWN, 0 }, |
| 464 +/* 90 */ {Cache_UNKNOWN, 0 }, |
| 465 +/* 91 */ {Cache_UNKNOWN, 0 }, |
| 466 +/* 92 */ {Cache_UNKNOWN, 0 }, |
| 467 +/* 93 */ {Cache_UNKNOWN, 0 }, |
| 468 +/* 94 */ {Cache_UNKNOWN, 0 }, |
| 469 +/* 95 */ {Cache_UNKNOWN, 0 }, |
| 470 +/* 96 */ {Cache_UNKNOWN, 0 }, |
| 471 +/* 97 */ {Cache_UNKNOWN, 0 }, |
| 472 +/* 98 */ {Cache_UNKNOWN, 0 }, |
| 473 +/* 99 */ {Cache_UNKNOWN, 0 }, |
| 474 +/* 9a */ {Cache_UNKNOWN, 0 }, |
| 475 +/* 9b */ {Cache_UNKNOWN, 0 }, |
| 476 +/* 9c */ {Cache_UNKNOWN, 0 }, |
| 477 +/* 9d */ {Cache_UNKNOWN, 0 }, |
| 478 +/* 9e */ {Cache_UNKNOWN, 0 }, |
| 479 +/* 9f */ {Cache_UNKNOWN, 0 }, |
| 480 +/* a0 */ {Cache_UNKNOWN, 0 }, |
| 481 +/* a1 */ {Cache_UNKNOWN, 0 }, |
| 482 +/* a2 */ {Cache_UNKNOWN, 0 }, |
| 483 +/* a3 */ {Cache_UNKNOWN, 0 }, |
| 484 +/* a4 */ {Cache_UNKNOWN, 0 }, |
| 485 +/* a5 */ {Cache_UNKNOWN, 0 }, |
| 486 +/* a6 */ {Cache_UNKNOWN, 0 }, |
| 487 +/* a7 */ {Cache_UNKNOWN, 0 }, |
| 488 +/* a8 */ {Cache_UNKNOWN, 0 }, |
| 489 +/* a9 */ {Cache_UNKNOWN, 0 }, |
| 490 +/* aa */ {Cache_UNKNOWN, 0 }, |
| 491 +/* ab */ {Cache_UNKNOWN, 0 }, |
| 492 +/* ac */ {Cache_UNKNOWN, 0 }, |
| 493 +/* ad */ {Cache_UNKNOWN, 0 }, |
| 494 +/* ae */ {Cache_UNKNOWN, 0 }, |
| 495 +/* af */ {Cache_UNKNOWN, 0 }, |
| 496 +/* b0 */ {Cache_TLBi, 0 }, |
| 497 +/* b1 */ {Cache_UNKNOWN, 0 }, |
| 498 +/* b2 */ {Cache_UNKNOWN, 0 }, |
| 499 +/* b3 */ {Cache_TLBd, 0 }, |
| 500 +/* b4 */ {Cache_UNKNOWN, 0 }, |
| 501 +/* b5 */ {Cache_UNKNOWN, 0 }, |
| 502 +/* b6 */ {Cache_UNKNOWN, 0 }, |
| 503 +/* b7 */ {Cache_UNKNOWN, 0 }, |
| 504 +/* b8 */ {Cache_UNKNOWN, 0 }, |
| 505 +/* b9 */ {Cache_UNKNOWN, 0 }, |
| 506 +/* ba */ {Cache_UNKNOWN, 0 }, |
| 507 +/* bb */ {Cache_UNKNOWN, 0 }, |
| 508 +/* bc */ {Cache_UNKNOWN, 0 }, |
| 509 +/* bd */ {Cache_UNKNOWN, 0 }, |
| 510 +/* be */ {Cache_UNKNOWN, 0 }, |
| 511 +/* bf */ {Cache_UNKNOWN, 0 }, |
| 512 +/* c0 */ {Cache_UNKNOWN, 0 }, |
| 513 +/* c1 */ {Cache_UNKNOWN, 0 }, |
| 514 +/* c2 */ {Cache_UNKNOWN, 0 }, |
| 515 +/* c3 */ {Cache_UNKNOWN, 0 }, |
| 516 +/* c4 */ {Cache_UNKNOWN, 0 }, |
| 517 +/* c5 */ {Cache_UNKNOWN, 0 }, |
| 518 +/* c6 */ {Cache_UNKNOWN, 0 }, |
| 519 +/* c7 */ {Cache_UNKNOWN, 0 }, |
| 520 +/* c8 */ {Cache_UNKNOWN, 0 }, |
| 521 +/* c9 */ {Cache_UNKNOWN, 0 }, |
| 522 +/* ca */ {Cache_UNKNOWN, 0 }, |
| 523 +/* cb */ {Cache_UNKNOWN, 0 }, |
| 524 +/* cc */ {Cache_UNKNOWN, 0 }, |
| 525 +/* cd */ {Cache_UNKNOWN, 0 }, |
| 526 +/* ce */ {Cache_UNKNOWN, 0 }, |
| 527 +/* cf */ {Cache_UNKNOWN, 0 }, |
| 528 +/* d0 */ {Cache_UNKNOWN, 0 }, |
| 529 +/* d1 */ {Cache_UNKNOWN, 0 }, |
| 530 +/* d2 */ {Cache_UNKNOWN, 0 }, |
| 531 +/* d3 */ {Cache_UNKNOWN, 0 }, |
| 532 +/* d4 */ {Cache_UNKNOWN, 0 }, |
| 533 +/* d5 */ {Cache_UNKNOWN, 0 }, |
| 534 +/* d6 */ {Cache_UNKNOWN, 0 }, |
| 535 +/* d7 */ {Cache_UNKNOWN, 0 }, |
| 536 +/* d8 */ {Cache_UNKNOWN, 0 }, |
| 537 +/* d9 */ {Cache_UNKNOWN, 0 }, |
| 538 +/* da */ {Cache_UNKNOWN, 0 }, |
| 539 +/* db */ {Cache_UNKNOWN, 0 }, |
| 540 +/* dc */ {Cache_UNKNOWN, 0 }, |
| 541 +/* dd */ {Cache_UNKNOWN, 0 }, |
| 542 +/* de */ {Cache_UNKNOWN, 0 }, |
| 543 +/* df */ {Cache_UNKNOWN, 0 }, |
| 544 +/* e0 */ {Cache_UNKNOWN, 0 }, |
| 545 +/* e1 */ {Cache_UNKNOWN, 0 }, |
| 546 +/* e2 */ {Cache_UNKNOWN, 0 }, |
| 547 +/* e3 */ {Cache_UNKNOWN, 0 }, |
| 548 +/* e4 */ {Cache_UNKNOWN, 0 }, |
| 549 +/* e5 */ {Cache_UNKNOWN, 0 }, |
| 550 +/* e6 */ {Cache_UNKNOWN, 0 }, |
| 551 +/* e7 */ {Cache_UNKNOWN, 0 }, |
| 552 +/* e8 */ {Cache_UNKNOWN, 0 }, |
| 553 +/* e9 */ {Cache_UNKNOWN, 0 }, |
| 554 +/* ea */ {Cache_UNKNOWN, 0 }, |
| 555 +/* eb */ {Cache_UNKNOWN, 0 }, |
| 556 +/* ec */ {Cache_UNKNOWN, 0 }, |
| 557 +/* ed */ {Cache_UNKNOWN, 0 }, |
| 558 +/* ee */ {Cache_UNKNOWN, 0 }, |
| 559 +/* ef */ {Cache_UNKNOWN, 0 }, |
| 560 +/* f0 */ {Cache_UNKNOWN, 0 }, |
| 561 +/* f1 */ {Cache_UNKNOWN, 0 }, |
| 562 +/* f2 */ {Cache_UNKNOWN, 0 }, |
| 563 +/* f3 */ {Cache_UNKNOWN, 0 }, |
| 564 +/* f4 */ {Cache_UNKNOWN, 0 }, |
| 565 +/* f5 */ {Cache_UNKNOWN, 0 }, |
| 566 +/* f6 */ {Cache_UNKNOWN, 0 }, |
| 567 +/* f7 */ {Cache_UNKNOWN, 0 }, |
| 568 +/* f8 */ {Cache_UNKNOWN, 0 }, |
| 569 +/* f9 */ {Cache_UNKNOWN, 0 }, |
| 570 +/* fa */ {Cache_UNKNOWN, 0 }, |
| 571 +/* fb */ {Cache_UNKNOWN, 0 }, |
| 572 +/* fc */ {Cache_UNKNOWN, 0 }, |
| 573 +/* fd */ {Cache_UNKNOWN, 0 }, |
| 574 +/* fe */ {Cache_UNKNOWN, 0 }, |
| 575 +/* ff */ {Cache_UNKNOWN, 0 } |
| 576 +}; |
| 577 + |
| 578 + |
| 579 +/* |
| 580 + * use the above table to determine the CacheEntryLineSize. |
| 581 + */ |
| 582 +static void |
| 583 +getIntelCacheEntryLineSize(unsigned long val, int *level, |
| 584 + unsigned long *lineSize) |
| 585 +{ |
| 586 + CacheType type; |
| 587 + |
| 588 + type = CacheMap[val].type; |
| 589 + /* only interested in data caches */ |
| 590 + /* NOTE val = 0x40 is a special value that means no L2 or L3 cache. |
| 591 + * this data check has the side effect of rejecting that entry. If |
| 592 + * that wasn't the case, we could have to reject it explicitly */ |
| 593 + if (CacheMap[val].lineSize == 0) { |
| 594 + return; |
| 595 + } |
| 596 + /* look at the caches, skip types we aren't interested in. |
| 597 + * if we already have a value for a lower level cache, skip the |
| 598 + * current entry */ |
| 599 + if ((type == Cache_L1)|| (type == Cache_L1d)) { |
| 600 + *level = 1; |
| 601 + *lineSize = CacheMap[val].lineSize; |
| 602 + } else if ((*level >= 2) && ((type == Cache_L2) || (type == Cache_L2d))) { |
| 603 + *level = 2; |
| 604 + *lineSize = CacheMap[val].lineSize; |
| 605 + } else if ((*level >= 3) && ((type == Cache_L3) || (type == Cache_L3d))) { |
| 606 + *level = 3; |
| 607 + *lineSize = CacheMap[val].lineSize; |
| 608 + } |
| 609 + return; |
| 610 +} |
| 611 + |
| 612 + |
| 613 +static void |
| 614 +getIntelRegisterCacheLineSize(unsigned long val, |
| 615 + int *level, unsigned long *lineSize) |
| 616 +{ |
| 617 + getIntelCacheEntryLineSize(val >> 24 & 0xff, level, lineSize); |
| 618 + getIntelCacheEntryLineSize(val >> 16 & 0xff, level, lineSize); |
| 619 + getIntelCacheEntryLineSize(val >> 8 & 0xff, level, lineSize); |
| 620 + getIntelCacheEntryLineSize(val & 0xff, level, lineSize); |
| 621 +} |
| 622 + |
| 623 +/* |
| 624 + * returns '0' if no recognized cache is found, or if the cache |
| 625 + * information is supported by this processor |
| 626 + */ |
| 627 +static unsigned long |
| 628 +getIntelCacheLineSize(int cpuidLevel) |
| 629 +{ |
| 630 + int level = 4; |
| 631 + unsigned long lineSize = 0; |
| 632 + unsigned long eax, ebx, ecx, edx; |
| 633 + int repeat, count; |
| 634 + |
| 635 + if (cpuidLevel < 2) { |
| 636 + return 0; |
| 637 + } |
| 638 + |
| 639 + /* command '2' of the cpuid is intel's cache info call. Each byte of the |
| 640 + * 4 registers contain a potential descriptor for the cache. The CacheMap |
| 641 + * table maps the cache entry with the processor cache. Register 'al' |
| 642 + * contains a count value that cpuid '2' needs to be called in order to |
| 643 + * find all the cache descriptors. Only registers with the high bit set |
| 644 + * to 'zero' have valid descriptors. This code loops through all the |
| 645 + * required calls to cpuid '2' and passes any valid descriptors it finds |
| 646 + * to the getIntelRegisterCacheLineSize code, which breaks the registers |
| 647 + * down into their component descriptors. In the end the lineSize of the |
| 648 + * lowest level cache data cache is returned. */ |
| 649 + freebl_cpuid(2, &eax, &ebx, &ecx, &edx); |
| 650 + repeat = eax & 0xf; |
| 651 + for (count = 0; count < repeat; count++) { |
| 652 + if ((eax & 0x80000000) == 0) { |
| 653 + getIntelRegisterCacheLineSize(eax & 0xffffff00, &level, &lineSize); |
| 654 + } |
| 655 + if ((ebx & 0x80000000) == 0) { |
| 656 + getIntelRegisterCacheLineSize(ebx, &level, &lineSize); |
| 657 + } |
| 658 + if ((ecx & 0x80000000) == 0) { |
| 659 + getIntelRegisterCacheLineSize(ecx, &level, &lineSize); |
| 660 + } |
| 661 + if ((edx & 0x80000000) == 0) { |
| 662 + getIntelRegisterCacheLineSize(edx, &level, &lineSize); |
| 663 + } |
| 664 + if (count+1 != repeat) { |
| 665 + freebl_cpuid(2, &eax, &ebx, &ecx, &edx); |
| 666 + } |
| 667 + } |
| 668 + return lineSize; |
| 669 +} |
| 670 + |
| 671 +/* |
| 672 + * returns '0' if the cache info is not supported by this processor. |
| 673 + * This is based on the AMD extended cache commands for cpuid. |
| 674 + * (see "AMD Processor Recognition Application Note" Publication 20734). |
| 675 + * Some other processors use the identical scheme. |
| 676 + * (see "Processor Recognition, Transmeta Corporation"). |
| 677 + */ |
| 678 +static unsigned long |
| 679 +getOtherCacheLineSize(unsigned long cpuidLevel) |
| 680 +{ |
| 681 + unsigned long lineSize = 0; |
| 682 + unsigned long eax, ebx, ecx, edx; |
| 683 + |
| 684 + /* get the Extended CPUID level */ |
| 685 + freebl_cpuid(0x80000000, &eax, &ebx, &ecx, &edx); |
| 686 + cpuidLevel = eax; |
| 687 + |
| 688 + if (cpuidLevel >= 0x80000005) { |
| 689 + freebl_cpuid(0x80000005, &eax, &ebx, &ecx, &edx); |
| 690 + lineSize = ecx & 0xff; /* line Size, L1 Data Cache */ |
| 691 + } |
| 692 + return lineSize; |
| 693 +} |
| 694 + |
| 695 +static const char * const manMap[] = { |
| 696 +#define INTEL 0 |
| 697 + "GenuineIntel", |
| 698 +#define AMD 1 |
| 699 + "AuthenticAMD", |
| 700 +#define CYRIX 2 |
| 701 + "CyrixInstead", |
| 702 +#define CENTAUR 2 |
| 703 + "CentaurHauls", |
| 704 +#define NEXGEN 3 |
| 705 + "NexGenDriven", |
| 706 +#define TRANSMETA 4 |
| 707 + "GenuineTMx86", |
| 708 +#define RISE 5 |
| 709 + "RiseRiseRise", |
| 710 +#define UMC 6 |
| 711 + "UMC UMC UMC ", |
| 712 +#define SIS 7 |
| 713 + "Sis Sis Sis ", |
| 714 +#define NATIONAL 8 |
| 715 + "Geode by NSC", |
| 716 +}; |
| 717 + |
| 718 +static const int n_manufacturers = sizeof(manMap)/sizeof(manMap[0]); |
| 719 + |
| 720 + |
| 721 +#define MAN_UNKNOWN 9 |
| 722 + |
| 723 +#if !defined(AMD_64) |
| 724 +#define SSE2_FLAG (1<<26) |
| 725 +unsigned long |
| 726 +s_mpi_is_sse2() |
| 727 +{ |
| 728 + unsigned long eax, ebx, ecx, edx; |
| 729 + int manufacturer = MAN_UNKNOWN; |
| 730 + int i; |
| 731 + char string[13]; |
| 732 + |
| 733 + if (is386() || is486()) { |
| 734 + return 0; |
| 735 + } |
| 736 + freebl_cpuid(0, &eax, &ebx, &ecx, &edx); |
| 737 + *(int *)string = ebx; |
| 738 + *(int *)&string[4] = edx; |
| 739 + *(int *)&string[8] = ecx; |
| 740 + string[12] = 0; |
| 741 + |
| 742 + /* has no SSE2 extensions */ |
| 743 + if (eax == 0) { |
| 744 + return 0; |
| 745 + } |
| 746 + |
| 747 + for (i=0; i < n_manufacturers; i++) { |
| 748 + if ( strcmp(manMap[i],string) == 0) { |
| 749 + manufacturer = i; |
| 750 + break; |
| 751 + } |
| 752 + } |
| 753 + |
| 754 + freebl_cpuid(1,&eax,&ebx,&ecx,&edx); |
| 755 + return (edx & SSE2_FLAG) == SSE2_FLAG; |
| 756 +} |
| 757 +#endif |
| 758 + |
| 759 +unsigned long |
| 760 +s_mpi_getProcessorLineSize() |
| 761 +{ |
| 762 + unsigned long eax, ebx, ecx, edx; |
| 763 + unsigned long cpuidLevel; |
| 764 + unsigned long cacheLineSize = 0; |
| 765 + int manufacturer = MAN_UNKNOWN; |
| 766 + int i; |
| 767 + char string[65]; |
| 768 + |
| 769 +#if !defined(AMD_64) |
| 770 + if (is386()) { |
| 771 + return 0; /* 386 had no cache */ |
| 772 + } if (is486()) { |
| 773 + return 32; /* really? need more info */ |
| 774 + } |
| 775 +#endif |
| 776 + |
| 777 + /* Pentium, cpuid command is available */ |
| 778 + freebl_cpuid(0, &eax, &ebx, &ecx, &edx); |
| 779 + cpuidLevel = eax; |
| 780 + *(int *)string = ebx; |
| 781 + *(int *)&string[4] = edx; |
| 782 + *(int *)&string[8] = ecx; |
| 783 + string[12] = 0; |
| 784 + |
| 785 + manufacturer = MAN_UNKNOWN; |
| 786 + for (i=0; i < n_manufacturers; i++) { |
| 787 + if ( strcmp(manMap[i],string) == 0) { |
| 788 + manufacturer = i; |
| 789 + } |
| 790 + } |
| 791 + |
| 792 + if (manufacturer == INTEL) { |
| 793 + cacheLineSize = getIntelCacheLineSize(cpuidLevel); |
| 794 + } else { |
| 795 + cacheLineSize = getOtherCacheLineSize(cpuidLevel); |
| 796 + } |
| 797 + /* doesn't support cache info based on cpuid. This means |
| 798 + * an old pentium class processor, which have cache lines of |
| 799 + * 32. If we learn differently, we can use a switch based on |
| 800 + * the Manufacturer id */ |
| 801 + if (cacheLineSize == 0) { |
| 802 + cacheLineSize = 32; |
| 803 + } |
| 804 + return cacheLineSize; |
| 805 +} |
| 806 +#define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED 1 |
| 807 +#endif |
| 808 + |
| 809 +#if defined(__ppc64__) |
| 810 +/* |
| 811 + * Sigh, The PPC has some really nice features to help us determine cache |
| 812 + * size, since it had lots of direct control functions to do so. The POWER |
| 813 + * processor even has an instruction to do this, but it was dropped in |
| 814 + * PowerPC. Unfortunately most of them are not available in user mode. |
| 815 + * |
| 816 + * The dcbz function would be a great way to determine cache line size except |
| 817 + * 1) it only works on write-back memory (it throws an exception otherwise), |
| 818 + * and 2) because so many mac programs 'knew' the processor cache size was |
| 819 + * 32 bytes, they used this instruction as a fast 'zero 32 bytes'. Now the new |
| 820 + * G5 processor has 128 byte cache, but dcbz only clears 32 bytes to keep |
| 821 + * these programs happy. dcbzl work if 64 bit instructions are supported. |
| 822 + * If you know 64 bit instructions are supported, and that stack is |
| 823 + * write-back, you can use this code. |
| 824 + */ |
| 825 +#include "memory.h" |
| 826 + |
| 827 +/* clear the cache line that contains 'array' */ |
| 828 +static inline void dcbzl(char *array) |
| 829 +{ |
| 830 + register char *a asm("r2") = array; |
| 831 + __asm__ __volatile__( "dcbzl %0,r0" : "=r" (a): "0"(a) ); |
| 832 +} |
| 833 + |
| 834 + |
| 835 +#define PPC_DO_ALIGN(x,y) ((char *)\ |
| 836 + ((((long long) (x))+((y)-1))&~((y)-1))) |
| 837 + |
| 838 +#define PPC_MAX_LINE_SIZE 256 |
| 839 +unsigned long |
| 840 +s_mpi_getProcessorLineSize() |
| 841 +{ |
| 842 + char testArray[2*PPC_MAX_LINE_SIZE+1]; |
| 843 + char *test; |
| 844 + int i; |
| 845 + |
| 846 + /* align the array on a maximum line size boundary, so we |
| 847 + * know we are starting to clear from the first address */ |
| 848 + test = PPC_DO_ALIGN(testArray, PPC_MAX_LINE_SIZE); |
| 849 + /* set all the values to 1's */ |
| 850 + memset(test, 0xff, PPC_MAX_LINE_SIZE); |
| 851 + /* clear one cache block starting at 'test' */ |
| 852 + dcbzl(test); |
| 853 + |
| 854 + /* find the size of the cleared area, that's our block size */ |
| 855 + for (i=PPC_MAX_LINE_SIZE; i != 0; i = i/2) { |
| 856 + if (test[i-1] == 0) { |
| 857 + return i; |
| 858 + } |
| 859 + } |
| 860 + return 0; |
| 861 +} |
| 862 + |
| 863 +#define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED 1 |
| 864 +#endif |
| 865 + |
| 866 + |
| 867 +/* |
| 868 + * put other processor and platform specific cache code here |
| 869 + * return the smallest cache line size in bytes on the processor |
| 870 + * (usually the L1 cache). If the OS has a call, this would be |
| 871 + * a greate place to put it. |
| 872 + * |
| 873 + * If there is no cache, return 0; |
| 874 + * |
| 875 + * define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED so the generic functions |
| 876 + * below aren't compiled. |
| 877 + * |
| 878 + */ |
| 879 + |
| 880 + |
| 881 +/* target.mk can define MPI_CACHE_LINE_SIZE if it's common for the family or |
| 882 + * OS */ |
| 883 +#if defined(MPI_CACHE_LINE_SIZE) && !defined(MPI_GET_PROCESSOR_LINE_SIZE_DEFINE
D) |
| 884 + |
| 885 +unsigned long |
| 886 +s_mpi_getProcessorLineSize() |
| 887 +{ |
| 888 + return MPI_CACHE_LINE_SIZE; |
| 889 +} |
| 890 +#define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED 1 |
| 891 +#endif |
| 892 + |
| 893 + |
| 894 +/* If no way to get the processor cache line size has been defined, assume |
| 895 + * it's 32 bytes (most common value, does not significantly impact performance) |
| 896 + */ |
| 897 +#ifndef MPI_GET_PROCESSOR_LINE_SIZE_DEFINED |
| 898 +unsigned long |
| 899 +s_mpi_getProcessorLineSize() |
| 900 +{ |
| 901 + return 32; |
| 902 +} |
| 903 +#endif |
| 904 + |
| 905 +#ifdef TEST_IT |
| 906 +#include <stdio.h> |
| 907 + |
| 908 +main() |
| 909 +{ |
| 910 + printf("line size = %d\n", s_mpi_getProcessorLineSize()); |
| 911 +} |
| 912 +#endif |
| 913 diff --git a/net/third_party/nss/ssl/mpi/mpi-config.h b/net/third_party/nss/ssl/
mpi/mpi-config.h |
| 914 new file mode 100644 |
| 915 index 0000000..00a0acf |
| 916 --- /dev/null |
| 917 +++ b/net/third_party/nss/ssl/mpi/mpi-config.h |
| 918 @@ -0,0 +1,112 @@ |
| 919 +/* Default configuration for MPI library |
| 920 + * |
| 921 + * ***** BEGIN LICENSE BLOCK ***** |
| 922 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 923 + * |
| 924 + * The contents of this file are subject to the Mozilla Public License Version |
| 925 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 926 + * the License. You may obtain a copy of the License at |
| 927 + * http://www.mozilla.org/MPL/ |
| 928 + * |
| 929 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 930 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 931 + * for the specific language governing rights and limitations under the |
| 932 + * License. |
| 933 + * |
| 934 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 935 + * |
| 936 + * The Initial Developer of the Original Code is |
| 937 + * Michael J. Fromberger. |
| 938 + * Portions created by the Initial Developer are Copyright (C) 1997 |
| 939 + * the Initial Developer. All Rights Reserved. |
| 940 + * |
| 941 + * Contributor(s): |
| 942 + * Netscape Communications Corporation |
| 943 + * |
| 944 + * Alternatively, the contents of this file may be used under the terms of |
| 945 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 946 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 947 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 948 + * of those above. If you wish to allow use of your version of this file only |
| 949 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 950 + * use your version of this file under the terms of the MPL, indicate your |
| 951 + * decision by deleting the provisions above and replace them with the notice |
| 952 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 953 + * the provisions above, a recipient may use your version of this file under |
| 954 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 955 + * |
| 956 + * ***** END LICENSE BLOCK ***** */ |
| 957 +/* $Id: mpi-config.h,v 1.5 2004/04/25 15:03:10 gerv%gerv.net Exp $ */ |
| 958 + |
| 959 +#ifndef MPI_CONFIG_H_ |
| 960 +#define MPI_CONFIG_H_ |
| 961 + |
| 962 +/* |
| 963 + For boolean options, |
| 964 + 0 = no |
| 965 + 1 = yes |
| 966 + |
| 967 + Other options are documented individually. |
| 968 + |
| 969 + */ |
| 970 + |
| 971 +#ifndef MP_IOFUNC |
| 972 +#define MP_IOFUNC 0 /* include mp_print() ? */ |
| 973 +#endif |
| 974 + |
| 975 +#ifndef MP_MODARITH |
| 976 +#define MP_MODARITH 1 /* include modular arithmetic ? */ |
| 977 +#endif |
| 978 + |
| 979 +#ifndef MP_NUMTH |
| 980 +#define MP_NUMTH 1 /* include number theoretic functions? */ |
| 981 +#endif |
| 982 + |
| 983 +#ifndef MP_LOGTAB |
| 984 +#define MP_LOGTAB 1 /* use table of logs instead of log()? */ |
| 985 +#endif |
| 986 + |
| 987 +#ifndef MP_MEMSET |
| 988 +#define MP_MEMSET 1 /* use memset() to zero buffers? */ |
| 989 +#endif |
| 990 + |
| 991 +#ifndef MP_MEMCPY |
| 992 +#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */ |
| 993 +#endif |
| 994 + |
| 995 +#ifndef MP_CRYPTO |
| 996 +#define MP_CRYPTO 1 /* erase memory on free? */ |
| 997 +#endif |
| 998 + |
| 999 +#ifndef MP_ARGCHK |
| 1000 +/* |
| 1001 + 0 = no parameter checks |
| 1002 + 1 = runtime checks, continue execution and return an error to caller |
| 1003 + 2 = assertions; dump core on parameter errors |
| 1004 + */ |
| 1005 +#ifdef DEBUG |
| 1006 +#define MP_ARGCHK 2 /* how to check input arguments */ |
| 1007 +#else |
| 1008 +#define MP_ARGCHK 1 /* how to check input arguments */ |
| 1009 +#endif |
| 1010 +#endif |
| 1011 + |
| 1012 +#ifndef MP_DEBUG |
| 1013 +#define MP_DEBUG 0 /* print diagnostic output? */ |
| 1014 +#endif |
| 1015 + |
| 1016 +#ifndef MP_DEFPREC |
| 1017 +#define MP_DEFPREC 64 /* default precision, in digits */ |
| 1018 +#endif |
| 1019 + |
| 1020 +#ifndef MP_MACRO |
| 1021 +#define MP_MACRO 0 /* use macros for frequent calls? */ |
| 1022 +#endif |
| 1023 + |
| 1024 +#ifndef MP_SQUARE |
| 1025 +#define MP_SQUARE 1 /* use separate squaring code? */ |
| 1026 +#endif |
| 1027 + |
| 1028 +#endif /* ifndef MPI_CONFIG_H_ */ |
| 1029 + |
| 1030 + |
| 1031 diff --git a/net/third_party/nss/ssl/mpi/mpi-priv.h b/net/third_party/nss/ssl/mp
i/mpi-priv.h |
| 1032 new file mode 100644 |
| 1033 index 0000000..8efaf3c |
| 1034 --- /dev/null |
| 1035 +++ b/net/third_party/nss/ssl/mpi/mpi-priv.h |
| 1036 @@ -0,0 +1,320 @@ |
| 1037 +/* |
| 1038 + * mpi-priv.h - Private header file for MPI |
| 1039 + * Arbitrary precision integer arithmetic library |
| 1040 + * |
| 1041 + * NOTE WELL: the content of this header file is NOT part of the "public" |
| 1042 + * API for the MPI library, and may change at any time. |
| 1043 + * Application programs that use libmpi should NOT include this header file. |
| 1044 + * |
| 1045 + * ***** BEGIN LICENSE BLOCK ***** |
| 1046 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 1047 + * |
| 1048 + * The contents of this file are subject to the Mozilla Public License Version |
| 1049 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 1050 + * the License. You may obtain a copy of the License at |
| 1051 + * http://www.mozilla.org/MPL/ |
| 1052 + * |
| 1053 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 1054 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 1055 + * for the specific language governing rights and limitations under the |
| 1056 + * License. |
| 1057 + * |
| 1058 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 1059 + * |
| 1060 + * The Initial Developer of the Original Code is |
| 1061 + * Michael J. Fromberger. |
| 1062 + * Portions created by the Initial Developer are Copyright (C) 1998 |
| 1063 + * the Initial Developer. All Rights Reserved. |
| 1064 + * |
| 1065 + * Contributor(s): |
| 1066 + * Netscape Communications Corporation |
| 1067 + * |
| 1068 + * Alternatively, the contents of this file may be used under the terms of |
| 1069 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 1070 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 1071 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 1072 + * of those above. If you wish to allow use of your version of this file only |
| 1073 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 1074 + * use your version of this file under the terms of the MPL, indicate your |
| 1075 + * decision by deleting the provisions above and replace them with the notice |
| 1076 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 1077 + * the provisions above, a recipient may use your version of this file under |
| 1078 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 1079 + * |
| 1080 + * ***** END LICENSE BLOCK ***** */ |
| 1081 +/* $Id: mpi-priv.h,v 1.23 2010/05/02 22:36:41 nelson%bolyard.com Exp $ */ |
| 1082 +#ifndef _MPI_PRIV_H_ |
| 1083 +#define _MPI_PRIV_H_ 1 |
| 1084 + |
| 1085 +#include "mpi.h" |
| 1086 +#include <stdlib.h> |
| 1087 +#include <string.h> |
| 1088 +#include <ctype.h> |
| 1089 + |
| 1090 +#if MP_DEBUG |
| 1091 +#include <stdio.h> |
| 1092 + |
| 1093 +#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);} |
| 1094 +#else |
| 1095 +#define DIAG(T,V) |
| 1096 +#endif |
| 1097 + |
| 1098 +/* If we aren't using a wired-in logarithm table, we need to include |
| 1099 + the math library to get the log() function |
| 1100 + */ |
| 1101 + |
| 1102 +/* {{{ s_logv_2[] - log table for 2 in various bases */ |
| 1103 + |
| 1104 +#if MP_LOGTAB |
| 1105 +/* |
| 1106 + A table of the logs of 2 for various bases (the 0 and 1 entries of |
| 1107 + this table are meaningless and should not be referenced). |
| 1108 + |
| 1109 + This table is used to compute output lengths for the mp_toradix() |
| 1110 + function. Since a number n in radix r takes up about log_r(n) |
| 1111 + digits, we estimate the output size by taking the least integer |
| 1112 + greater than log_r(n), where: |
| 1113 + |
| 1114 + log_r(n) = log_2(n) * log_r(2) |
| 1115 + |
| 1116 + This table, therefore, is a table of log_r(2) for 2 <= r <= 36, |
| 1117 + which are the output bases supported. |
| 1118 + */ |
| 1119 + |
| 1120 +extern const float s_logv_2[]; |
| 1121 +#define LOG_V_2(R) s_logv_2[(R)] |
| 1122 + |
| 1123 +#else |
| 1124 + |
| 1125 +/* |
| 1126 + If MP_LOGTAB is not defined, use the math library to compute the |
| 1127 + logarithms on the fly. Otherwise, use the table. |
| 1128 + Pick which works best for your system. |
| 1129 + */ |
| 1130 + |
| 1131 +#include <math.h> |
| 1132 +#define LOG_V_2(R) (log(2.0)/log(R)) |
| 1133 + |
| 1134 +#endif /* if MP_LOGTAB */ |
| 1135 + |
| 1136 +/* }}} */ |
| 1137 + |
| 1138 +/* {{{ Digit arithmetic macros */ |
| 1139 + |
| 1140 +/* |
| 1141 + When adding and multiplying digits, the results can be larger than |
| 1142 + can be contained in an mp_digit. Thus, an mp_word is used. These |
| 1143 + macros mask off the upper and lower digits of the mp_word (the |
| 1144 + mp_word may be more than 2 mp_digits wide, but we only concern |
| 1145 + ourselves with the low-order 2 mp_digits) |
| 1146 + */ |
| 1147 + |
| 1148 +#define CARRYOUT(W) (mp_digit)((W)>>DIGIT_BIT) |
| 1149 +#define ACCUM(W) (mp_digit)(W) |
| 1150 + |
| 1151 +#define MP_MIN(a,b) (((a) < (b)) ? (a) : (b)) |
| 1152 +#define MP_MAX(a,b) (((a) > (b)) ? (a) : (b)) |
| 1153 +#define MP_HOWMANY(a,b) (((a) + (b) - 1)/(b)) |
| 1154 +#define MP_ROUNDUP(a,b) (MP_HOWMANY(a,b) * (b)) |
| 1155 + |
| 1156 +/* }}} */ |
| 1157 + |
| 1158 +/* {{{ Comparison constants */ |
| 1159 + |
| 1160 +#define MP_LT -1 |
| 1161 +#define MP_EQ 0 |
| 1162 +#define MP_GT 1 |
| 1163 + |
| 1164 +/* }}} */ |
| 1165 + |
| 1166 +/* {{{ private function declarations */ |
| 1167 + |
| 1168 +/* |
| 1169 + If MP_MACRO is false, these will be defined as actual functions; |
| 1170 + otherwise, suitable macro definitions will be used. This works |
| 1171 + around the fact that ANSI C89 doesn't support an 'inline' keyword |
| 1172 + (although I hear C9x will ... about bloody time). At present, the |
| 1173 + macro definitions are identical to the function bodies, but they'll |
| 1174 + expand in place, instead of generating a function call. |
| 1175 + |
| 1176 + I chose these particular functions to be made into macros because |
| 1177 + some profiling showed they are called a lot on a typical workload, |
| 1178 + and yet they are primarily housekeeping. |
| 1179 + */ |
| 1180 +#if MP_MACRO == 0 |
| 1181 + void s_mp_setz(mp_digit *dp, mp_size count); /* zero digits */ |
| 1182 + void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count); /* copy *
/ |
| 1183 + void *s_mp_alloc(size_t nb, size_t ni); /* general allocator */ |
| 1184 + void s_mp_free(void *ptr); /* general free function */ |
| 1185 +extern unsigned long mp_allocs; |
| 1186 +extern unsigned long mp_frees; |
| 1187 +extern unsigned long mp_copies; |
| 1188 +#else |
| 1189 + |
| 1190 + /* Even if these are defined as macros, we need to respect the settings |
| 1191 + of the MP_MEMSET and MP_MEMCPY configuration options... |
| 1192 + */ |
| 1193 + #if MP_MEMSET == 0 |
| 1194 + #define s_mp_setz(dp, count) \ |
| 1195 + {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;} |
| 1196 + #else |
| 1197 + #define s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit)) |
| 1198 + #endif /* MP_MEMSET */ |
| 1199 + |
| 1200 + #if MP_MEMCPY == 0 |
| 1201 + #define s_mp_copy(sp, dp, count) \ |
| 1202 + {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];} |
| 1203 + #else |
| 1204 + #define s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit)) |
| 1205 + #endif /* MP_MEMCPY */ |
| 1206 + |
| 1207 + #define s_mp_alloc(nb, ni) calloc(nb, ni) |
| 1208 + #define s_mp_free(ptr) {if(ptr) free(ptr);} |
| 1209 +#endif /* MP_MACRO */ |
| 1210 + |
| 1211 +mp_err s_mp_grow(mp_int *mp, mp_size min); /* increase allocated size */ |
| 1212 +mp_err s_mp_pad(mp_int *mp, mp_size min); /* left pad with zeroes */ |
| 1213 + |
| 1214 +#if MP_MACRO == 0 |
| 1215 + void s_mp_clamp(mp_int *mp); /* clip leading zeroes */ |
| 1216 +#else |
| 1217 + #define s_mp_clamp(mp)\ |
| 1218 + { mp_size used = MP_USED(mp); \ |
| 1219 + while (used > 1 && DIGIT(mp, used - 1) == 0) --used; \ |
| 1220 + MP_USED(mp) = used; \ |
| 1221 + } |
| 1222 +#endif /* MP_MACRO */ |
| 1223 + |
| 1224 +void s_mp_exch(mp_int *a, mp_int *b); /* swap a and b in place */ |
| 1225 + |
| 1226 +mp_err s_mp_lshd(mp_int *mp, mp_size p); /* left-shift by p digits */ |
| 1227 +void s_mp_rshd(mp_int *mp, mp_size p); /* right-shift by p digits */ |
| 1228 +mp_err s_mp_mul_2d(mp_int *mp, mp_digit d); /* multiply by 2^d in place */ |
| 1229 +void s_mp_div_2d(mp_int *mp, mp_digit d); /* divide by 2^d in place */ |
| 1230 +void s_mp_mod_2d(mp_int *mp, mp_digit d); /* modulo 2^d in place */ |
| 1231 +void s_mp_div_2(mp_int *mp); /* divide by 2 in place */ |
| 1232 +mp_err s_mp_mul_2(mp_int *mp); /* multiply by 2 in place */ |
| 1233 +mp_err s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd); |
| 1234 + /* normalize for division */ |
| 1235 +mp_err s_mp_add_d(mp_int *mp, mp_digit d); /* unsigned digit addition */ |
| 1236 +mp_err s_mp_sub_d(mp_int *mp, mp_digit d); /* unsigned digit subtract */ |
| 1237 +mp_err s_mp_mul_d(mp_int *mp, mp_digit d); /* unsigned digit multiply */ |
| 1238 +mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r); |
| 1239 + /* unsigned digit divide */ |
| 1240 +mp_err s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu); |
| 1241 + /* Barrett reduction */ |
| 1242 +mp_err s_mp_add(mp_int *a, const mp_int *b); /* magnitude addition */ |
| 1243 +mp_err s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c); |
| 1244 +mp_err s_mp_sub(mp_int *a, const mp_int *b); /* magnitude subtract */ |
| 1245 +mp_err s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c); |
| 1246 +mp_err s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset); |
| 1247 + /* a += b * RADIX^offset */ |
| 1248 +mp_err s_mp_mul(mp_int *a, const mp_int *b); /* magnitude multiply */ |
| 1249 +#if MP_SQUARE |
| 1250 +mp_err s_mp_sqr(mp_int *a); /* magnitude square */ |
| 1251 +#else |
| 1252 +#define s_mp_sqr(a) s_mp_mul(a, a) |
| 1253 +#endif |
| 1254 +mp_err s_mp_div(mp_int *rem, mp_int *div, mp_int *quot); /* magnitude div */ |
| 1255 +mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int
*c); |
| 1256 +mp_err s_mp_2expt(mp_int *a, mp_digit k); /* a = 2^k */ |
| 1257 +int s_mp_cmp(const mp_int *a, const mp_int *b); /* magnitude comparison */ |
| 1258 +int s_mp_cmp_d(const mp_int *a, mp_digit d); /* magnitude digit compare */ |
| 1259 +int s_mp_ispow2(const mp_int *v); /* is v a power of 2? */ |
| 1260 +int s_mp_ispow2d(mp_digit d); /* is d a power of 2? */ |
| 1261 + |
| 1262 +int s_mp_tovalue(char ch, int r); /* convert ch to value */ |
| 1263 +char s_mp_todigit(mp_digit val, int r, int low); /* convert val to digit */ |
| 1264 +int s_mp_outlen(int bits, int r); /* output length in bytes */ |
| 1265 +mp_digit s_mp_invmod_radix(mp_digit P); /* returns (P ** -1) mod RADIX */ |
| 1266 +mp_err s_mp_invmod_odd_m( const mp_int *a, const mp_int *m, mp_int *c); |
| 1267 +mp_err s_mp_invmod_2d( const mp_int *a, mp_size k, mp_int *c); |
| 1268 +mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c); |
| 1269 + |
| 1270 +#ifdef NSS_USE_COMBA |
| 1271 + |
| 1272 +#define IS_POWER_OF_2(a) ((a) && !((a) & ((a)-1))) |
| 1273 + |
| 1274 +void s_mp_mul_comba_4(const mp_int *A, const mp_int *B, mp_int *C); |
| 1275 +void s_mp_mul_comba_8(const mp_int *A, const mp_int *B, mp_int *C); |
| 1276 +void s_mp_mul_comba_16(const mp_int *A, const mp_int *B, mp_int *C); |
| 1277 +void s_mp_mul_comba_32(const mp_int *A, const mp_int *B, mp_int *C); |
| 1278 + |
| 1279 +void s_mp_sqr_comba_4(const mp_int *A, mp_int *B); |
| 1280 +void s_mp_sqr_comba_8(const mp_int *A, mp_int *B); |
| 1281 +void s_mp_sqr_comba_16(const mp_int *A, mp_int *B); |
| 1282 +void s_mp_sqr_comba_32(const mp_int *A, mp_int *B); |
| 1283 + |
| 1284 +#endif /* end NSS_USE_COMBA */ |
| 1285 + |
| 1286 +/* ------ mpv functions, operate on arrays of digits, not on mp_int's ------ */ |
| 1287 +#if defined (__OS2__) && defined (__IBMC__) |
| 1288 +#define MPI_ASM_DECL __cdecl |
| 1289 +#else |
| 1290 +#define MPI_ASM_DECL |
| 1291 +#endif |
| 1292 + |
| 1293 +#ifdef MPI_AMD64 |
| 1294 + |
| 1295 +mp_digit MPI_ASM_DECL s_mpv_mul_set_vec64(mp_digit*, mp_digit *, mp_size, mp_di
git); |
| 1296 +mp_digit MPI_ASM_DECL s_mpv_mul_add_vec64(mp_digit*, const mp_digit*, mp_size,
mp_digit); |
| 1297 + |
| 1298 +/* c = a * b */ |
| 1299 +#define s_mpv_mul_d(a, a_len, b, c) \ |
| 1300 + ((mp_digit *)c)[a_len] = s_mpv_mul_set_vec64(c, a, a_len, b) |
| 1301 + |
| 1302 +/* c += a * b */ |
| 1303 +#define s_mpv_mul_d_add(a, a_len, b, c) \ |
| 1304 + ((mp_digit *)c)[a_len] = s_mpv_mul_add_vec64(c, a, a_len, b) |
| 1305 + |
| 1306 + |
| 1307 +#else |
| 1308 + |
| 1309 +void MPI_ASM_DECL s_mpv_mul_d(const mp_digit *a, mp_size a_len, |
| 1310 + mp_digit b, mp_digit *c); |
| 1311 +void MPI_ASM_DECL s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, |
| 1312 + mp_digit b, mp_digit *c); |
| 1313 + |
| 1314 +#endif |
| 1315 + |
| 1316 +void MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a, |
| 1317 + mp_size a_len, mp_digit b, |
| 1318 + mp_digit *c); |
| 1319 +void MPI_ASM_DECL s_mpv_sqr_add_prop(const mp_digit *a, |
| 1320 + mp_size a_len, |
| 1321 + mp_digit *sqrs); |
| 1322 + |
| 1323 +mp_err MPI_ASM_DECL s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, |
| 1324 + mp_digit divisor, mp_digit *quot, mp_digit *rem); |
| 1325 + |
| 1326 +/* c += a * b * (MP_RADIX ** offset); */ |
| 1327 +#define s_mp_mul_d_add_offset(a, b, c, off) \ |
| 1328 +(s_mpv_mul_d_add_prop(MP_DIGITS(a), MP_USED(a), b, MP_DIGITS(c) + off), MP_OKAY
) |
| 1329 + |
| 1330 +typedef struct { |
| 1331 + mp_int N; /* modulus N */ |
| 1332 + mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */ |
| 1333 + mp_size b; /* R == 2 ** b, also b = # significant bits in N */ |
| 1334 +} mp_mont_modulus; |
| 1335 + |
| 1336 +mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c, |
| 1337 + mp_mont_modulus *mmm); |
| 1338 +mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm); |
| 1339 + |
| 1340 +/* |
| 1341 + * s_mpi_getProcessorLineSize() returns the size in bytes of the cache line |
| 1342 + * if a cache exists, or zero if there is no cache. If more than one |
| 1343 + * cache line exists, it should return the smallest line size (which is |
| 1344 + * usually the L1 cache). |
| 1345 + * |
| 1346 + * mp_modexp uses this information to make sure that private key information |
| 1347 + * isn't being leaked through the cache. |
| 1348 + * |
| 1349 + * see mpcpucache.c for the implementation. |
| 1350 + */ |
| 1351 +unsigned long s_mpi_getProcessorLineSize(); |
| 1352 + |
| 1353 +/* }}} */ |
| 1354 +#endif |
| 1355 + |
| 1356 + |
| 1357 diff --git a/net/third_party/nss/ssl/mpi/mpi.c b/net/third_party/nss/ssl/mpi/mpi
.c |
| 1358 new file mode 100644 |
| 1359 index 0000000..8cd6ca6 |
| 1360 --- /dev/null |
| 1361 +++ b/net/third_party/nss/ssl/mpi/mpi.c |
| 1362 @@ -0,0 +1,4852 @@ |
| 1363 +/* |
| 1364 + * mpi.c |
| 1365 + * |
| 1366 + * Arbitrary precision integer arithmetic library |
| 1367 + * |
| 1368 + * ***** BEGIN LICENSE BLOCK ***** |
| 1369 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 1370 + * |
| 1371 + * The contents of this file are subject to the Mozilla Public License Version |
| 1372 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 1373 + * the License. You may obtain a copy of the License at |
| 1374 + * http://www.mozilla.org/MPL/ |
| 1375 + * |
| 1376 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 1377 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 1378 + * for the specific language governing rights and limitations under the |
| 1379 + * License. |
| 1380 + * |
| 1381 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 1382 + * |
| 1383 + * The Initial Developer of the Original Code is |
| 1384 + * Michael J. Fromberger. |
| 1385 + * Portions created by the Initial Developer are Copyright (C) 1998 |
| 1386 + * the Initial Developer. All Rights Reserved. |
| 1387 + * |
| 1388 + * Contributor(s): |
| 1389 + * Netscape Communications Corporation |
| 1390 + * Douglas Stebila <douglas@stebila.ca> of Sun Laboratories. |
| 1391 + * |
| 1392 + * Alternatively, the contents of this file may be used under the terms of |
| 1393 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 1394 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 1395 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 1396 + * of those above. If you wish to allow use of your version of this file only |
| 1397 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 1398 + * use your version of this file under the terms of the MPL, indicate your |
| 1399 + * decision by deleting the provisions above and replace them with the notice |
| 1400 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 1401 + * the provisions above, a recipient may use your version of this file under |
| 1402 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 1403 + * |
| 1404 + * ***** END LICENSE BLOCK ***** */ |
| 1405 +/* $Id: mpi.c,v 1.47 2010/05/02 22:36:41 nelson%bolyard.com Exp $ */ |
| 1406 + |
| 1407 +#define MP_API_COMPATIBLE 1 |
| 1408 +#include "mpi-priv.h" |
| 1409 +#if defined(OSF1) |
| 1410 +#include <c_asm.h> |
| 1411 +#endif |
| 1412 + |
| 1413 +#if MP_LOGTAB |
| 1414 +/* |
| 1415 + A table of the logs of 2 for various bases (the 0 and 1 entries of |
| 1416 + this table are meaningless and should not be referenced). |
| 1417 + |
| 1418 + This table is used to compute output lengths for the mp_toradix() |
| 1419 + function. Since a number n in radix r takes up about log_r(n) |
| 1420 + digits, we estimate the output size by taking the least integer |
| 1421 + greater than log_r(n), where: |
| 1422 + |
| 1423 + log_r(n) = log_2(n) * log_r(2) |
| 1424 + |
| 1425 + This table, therefore, is a table of log_r(2) for 2 <= r <= 36, |
| 1426 + which are the output bases supported. |
| 1427 + */ |
| 1428 +#include "logtab.h" |
| 1429 +#endif |
| 1430 + |
| 1431 +/* {{{ Constant strings */ |
| 1432 + |
| 1433 +/* Constant strings returned by mp_strerror() */ |
| 1434 +static const char *mp_err_string[] = { |
| 1435 + "unknown result code", /* say what? */ |
| 1436 + "boolean true", /* MP_OKAY, MP_YES */ |
| 1437 + "boolean false", /* MP_NO */ |
| 1438 + "out of memory", /* MP_MEM */ |
| 1439 + "argument out of range", /* MP_RANGE */ |
| 1440 + "invalid input parameter", /* MP_BADARG */ |
| 1441 + "result is undefined" /* MP_UNDEF */ |
| 1442 +}; |
| 1443 + |
| 1444 +/* Value to digit maps for radix conversion */ |
| 1445 + |
| 1446 +/* s_dmap_1 - standard digits and letters */ |
| 1447 +static const char *s_dmap_1 = |
| 1448 + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; |
| 1449 + |
| 1450 +/* }}} */ |
| 1451 + |
| 1452 +unsigned long mp_allocs; |
| 1453 +unsigned long mp_frees; |
| 1454 +unsigned long mp_copies; |
| 1455 + |
| 1456 +/* {{{ Default precision manipulation */ |
| 1457 + |
| 1458 +/* Default precision for newly created mp_int's */ |
| 1459 +static mp_size s_mp_defprec = MP_DEFPREC; |
| 1460 + |
| 1461 +mp_size mp_get_prec(void) |
| 1462 +{ |
| 1463 + return s_mp_defprec; |
| 1464 + |
| 1465 +} /* end mp_get_prec() */ |
| 1466 + |
| 1467 +void mp_set_prec(mp_size prec) |
| 1468 +{ |
| 1469 + if(prec == 0) |
| 1470 + s_mp_defprec = MP_DEFPREC; |
| 1471 + else |
| 1472 + s_mp_defprec = prec; |
| 1473 + |
| 1474 +} /* end mp_set_prec() */ |
| 1475 + |
| 1476 +/* }}} */ |
| 1477 + |
| 1478 +/*------------------------------------------------------------------------*/ |
| 1479 +/* {{{ mp_init(mp) */ |
| 1480 + |
| 1481 +/* |
| 1482 + mp_init(mp) |
| 1483 + |
| 1484 + Initialize a new zero-valued mp_int. Returns MP_OKAY if successful, |
| 1485 + MP_MEM if memory could not be allocated for the structure. |
| 1486 + */ |
| 1487 + |
| 1488 +mp_err mp_init(mp_int *mp) |
| 1489 +{ |
| 1490 + return mp_init_size(mp, s_mp_defprec); |
| 1491 + |
| 1492 +} /* end mp_init() */ |
| 1493 + |
| 1494 +/* }}} */ |
| 1495 + |
| 1496 +/* {{{ mp_init_size(mp, prec) */ |
| 1497 + |
| 1498 +/* |
| 1499 + mp_init_size(mp, prec) |
| 1500 + |
| 1501 + Initialize a new zero-valued mp_int with at least the given |
| 1502 + precision; returns MP_OKAY if successful, or MP_MEM if memory could |
| 1503 + not be allocated for the structure. |
| 1504 + */ |
| 1505 + |
| 1506 +mp_err mp_init_size(mp_int *mp, mp_size prec) |
| 1507 +{ |
| 1508 + ARGCHK(mp != NULL && prec > 0, MP_BADARG); |
| 1509 + |
| 1510 + prec = MP_ROUNDUP(prec, s_mp_defprec); |
| 1511 + if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL) |
| 1512 + return MP_MEM; |
| 1513 + |
| 1514 + SIGN(mp) = ZPOS; |
| 1515 + USED(mp) = 1; |
| 1516 + ALLOC(mp) = prec; |
| 1517 + |
| 1518 + return MP_OKAY; |
| 1519 + |
| 1520 +} /* end mp_init_size() */ |
| 1521 + |
| 1522 +/* }}} */ |
| 1523 + |
| 1524 +/* {{{ mp_init_copy(mp, from) */ |
| 1525 + |
| 1526 +/* |
| 1527 + mp_init_copy(mp, from) |
| 1528 + |
| 1529 + Initialize mp as an exact copy of from. Returns MP_OKAY if |
| 1530 + successful, MP_MEM if memory could not be allocated for the new |
| 1531 + structure. |
| 1532 + */ |
| 1533 + |
| 1534 +mp_err mp_init_copy(mp_int *mp, const mp_int *from) |
| 1535 +{ |
| 1536 + ARGCHK(mp != NULL && from != NULL, MP_BADARG); |
| 1537 + |
| 1538 + if(mp == from) |
| 1539 + return MP_OKAY; |
| 1540 + |
| 1541 + if((DIGITS(mp) = s_mp_alloc(ALLOC(from), sizeof(mp_digit))) == NULL) |
| 1542 + return MP_MEM; |
| 1543 + |
| 1544 + s_mp_copy(DIGITS(from), DIGITS(mp), USED(from)); |
| 1545 + USED(mp) = USED(from); |
| 1546 + ALLOC(mp) = ALLOC(from); |
| 1547 + SIGN(mp) = SIGN(from); |
| 1548 + |
| 1549 + return MP_OKAY; |
| 1550 + |
| 1551 +} /* end mp_init_copy() */ |
| 1552 + |
| 1553 +/* }}} */ |
| 1554 + |
| 1555 +/* {{{ mp_copy(from, to) */ |
| 1556 + |
| 1557 +/* |
| 1558 + mp_copy(from, to) |
| 1559 + |
| 1560 + Copies the mp_int 'from' to the mp_int 'to'. It is presumed that |
| 1561 + 'to' has already been initialized (if not, use mp_init_copy() |
| 1562 + instead). If 'from' and 'to' are identical, nothing happens. |
| 1563 + */ |
| 1564 + |
| 1565 +mp_err mp_copy(const mp_int *from, mp_int *to) |
| 1566 +{ |
| 1567 + ARGCHK(from != NULL && to != NULL, MP_BADARG); |
| 1568 + |
| 1569 + if(from == to) |
| 1570 + return MP_OKAY; |
| 1571 + |
| 1572 + ++mp_copies; |
| 1573 + { /* copy */ |
| 1574 + mp_digit *tmp; |
| 1575 + |
| 1576 + /* |
| 1577 + If the allocated buffer in 'to' already has enough space to hold |
| 1578 + all the used digits of 'from', we'll re-use it to avoid hitting |
| 1579 + the memory allocater more than necessary; otherwise, we'd have |
| 1580 + to grow anyway, so we just allocate a hunk and make the copy as |
| 1581 + usual |
| 1582 + */ |
| 1583 + if(ALLOC(to) >= USED(from)) { |
| 1584 + s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from)); |
| 1585 + s_mp_copy(DIGITS(from), DIGITS(to), USED(from)); |
| 1586 + |
| 1587 + } else { |
| 1588 + if((tmp = s_mp_alloc(ALLOC(from), sizeof(mp_digit))) == NULL) |
| 1589 + return MP_MEM; |
| 1590 + |
| 1591 + s_mp_copy(DIGITS(from), tmp, USED(from)); |
| 1592 + |
| 1593 + if(DIGITS(to) != NULL) { |
| 1594 +#if MP_CRYPTO |
| 1595 + s_mp_setz(DIGITS(to), ALLOC(to)); |
| 1596 +#endif |
| 1597 + s_mp_free(DIGITS(to)); |
| 1598 + } |
| 1599 + |
| 1600 + DIGITS(to) = tmp; |
| 1601 + ALLOC(to) = ALLOC(from); |
| 1602 + } |
| 1603 + |
| 1604 + /* Copy the precision and sign from the original */ |
| 1605 + USED(to) = USED(from); |
| 1606 + SIGN(to) = SIGN(from); |
| 1607 + } /* end copy */ |
| 1608 + |
| 1609 + return MP_OKAY; |
| 1610 + |
| 1611 +} /* end mp_copy() */ |
| 1612 + |
| 1613 +/* }}} */ |
| 1614 + |
| 1615 +/* {{{ mp_exch(mp1, mp2) */ |
| 1616 + |
| 1617 +/* |
| 1618 + mp_exch(mp1, mp2) |
| 1619 + |
| 1620 + Exchange mp1 and mp2 without allocating any intermediate memory |
| 1621 + (well, unless you count the stack space needed for this call and the |
| 1622 + locals it creates...). This cannot fail. |
| 1623 + */ |
| 1624 + |
| 1625 +void mp_exch(mp_int *mp1, mp_int *mp2) |
| 1626 +{ |
| 1627 +#if MP_ARGCHK == 2 |
| 1628 + assert(mp1 != NULL && mp2 != NULL); |
| 1629 +#else |
| 1630 + if(mp1 == NULL || mp2 == NULL) |
| 1631 + return; |
| 1632 +#endif |
| 1633 + |
| 1634 + s_mp_exch(mp1, mp2); |
| 1635 + |
| 1636 +} /* end mp_exch() */ |
| 1637 + |
| 1638 +/* }}} */ |
| 1639 + |
| 1640 +/* {{{ mp_clear(mp) */ |
| 1641 + |
| 1642 +/* |
| 1643 + mp_clear(mp) |
| 1644 + |
| 1645 + Release the storage used by an mp_int, and void its fields so that |
| 1646 + if someone calls mp_clear() again for the same int later, we won't |
| 1647 + get tollchocked. |
| 1648 + */ |
| 1649 + |
| 1650 +void mp_clear(mp_int *mp) |
| 1651 +{ |
| 1652 + if(mp == NULL) |
| 1653 + return; |
| 1654 + |
| 1655 + if(DIGITS(mp) != NULL) { |
| 1656 +#if MP_CRYPTO |
| 1657 + s_mp_setz(DIGITS(mp), ALLOC(mp)); |
| 1658 +#endif |
| 1659 + s_mp_free(DIGITS(mp)); |
| 1660 + DIGITS(mp) = NULL; |
| 1661 + } |
| 1662 + |
| 1663 + USED(mp) = 0; |
| 1664 + ALLOC(mp) = 0; |
| 1665 + |
| 1666 +} /* end mp_clear() */ |
| 1667 + |
| 1668 +/* }}} */ |
| 1669 + |
| 1670 +/* {{{ mp_zero(mp) */ |
| 1671 + |
| 1672 +/* |
| 1673 + mp_zero(mp) |
| 1674 + |
| 1675 + Set mp to zero. Does not change the allocated size of the structure, |
| 1676 + and therefore cannot fail (except on a bad argument, which we ignore) |
| 1677 + */ |
| 1678 +void mp_zero(mp_int *mp) |
| 1679 +{ |
| 1680 + if(mp == NULL) |
| 1681 + return; |
| 1682 + |
| 1683 + s_mp_setz(DIGITS(mp), ALLOC(mp)); |
| 1684 + USED(mp) = 1; |
| 1685 + SIGN(mp) = ZPOS; |
| 1686 + |
| 1687 +} /* end mp_zero() */ |
| 1688 + |
| 1689 +/* }}} */ |
| 1690 + |
| 1691 +/* {{{ mp_set(mp, d) */ |
| 1692 + |
| 1693 +void mp_set(mp_int *mp, mp_digit d) |
| 1694 +{ |
| 1695 + if(mp == NULL) |
| 1696 + return; |
| 1697 + |
| 1698 + mp_zero(mp); |
| 1699 + DIGIT(mp, 0) = d; |
| 1700 + |
| 1701 +} /* end mp_set() */ |
| 1702 + |
| 1703 +/* }}} */ |
| 1704 + |
| 1705 +/* {{{ mp_set_int(mp, z) */ |
| 1706 + |
| 1707 +mp_err mp_set_int(mp_int *mp, long z) |
| 1708 +{ |
| 1709 + int ix; |
| 1710 + unsigned long v = labs(z); |
| 1711 + mp_err res; |
| 1712 + |
| 1713 + ARGCHK(mp != NULL, MP_BADARG); |
| 1714 + |
| 1715 + mp_zero(mp); |
| 1716 + if(z == 0) |
| 1717 + return MP_OKAY; /* shortcut for zero */ |
| 1718 + |
| 1719 + if (sizeof v <= sizeof(mp_digit)) { |
| 1720 + DIGIT(mp,0) = v; |
| 1721 + } else { |
| 1722 + for (ix = sizeof(long) - 1; ix >= 0; ix--) { |
| 1723 + if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY) |
| 1724 + return res; |
| 1725 + |
| 1726 + res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX)); |
| 1727 + if (res != MP_OKAY) |
| 1728 + return res; |
| 1729 + } |
| 1730 + } |
| 1731 + if(z < 0) |
| 1732 + SIGN(mp) = NEG; |
| 1733 + |
| 1734 + return MP_OKAY; |
| 1735 + |
| 1736 +} /* end mp_set_int() */ |
| 1737 + |
| 1738 +/* }}} */ |
| 1739 + |
| 1740 +/* {{{ mp_set_ulong(mp, z) */ |
| 1741 + |
| 1742 +mp_err mp_set_ulong(mp_int *mp, unsigned long z) |
| 1743 +{ |
| 1744 + int ix; |
| 1745 + mp_err res; |
| 1746 + |
| 1747 + ARGCHK(mp != NULL, MP_BADARG); |
| 1748 + |
| 1749 + mp_zero(mp); |
| 1750 + if(z == 0) |
| 1751 + return MP_OKAY; /* shortcut for zero */ |
| 1752 + |
| 1753 + if (sizeof z <= sizeof(mp_digit)) { |
| 1754 + DIGIT(mp,0) = z; |
| 1755 + } else { |
| 1756 + for (ix = sizeof(long) - 1; ix >= 0; ix--) { |
| 1757 + if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY) |
| 1758 + return res; |
| 1759 + |
| 1760 + res = s_mp_add_d(mp, (mp_digit)((z >> (ix * CHAR_BIT)) & UCHAR_MAX)); |
| 1761 + if (res != MP_OKAY) |
| 1762 + return res; |
| 1763 + } |
| 1764 + } |
| 1765 + return MP_OKAY; |
| 1766 +} /* end mp_set_ulong() */ |
| 1767 + |
| 1768 +/* }}} */ |
| 1769 + |
| 1770 +/*------------------------------------------------------------------------*/ |
| 1771 +/* {{{ Digit arithmetic */ |
| 1772 + |
| 1773 +/* {{{ mp_add_d(a, d, b) */ |
| 1774 + |
| 1775 +/* |
| 1776 + mp_add_d(a, d, b) |
| 1777 + |
| 1778 + Compute the sum b = a + d, for a single digit d. Respects the sign of |
| 1779 + its primary addend (single digits are unsigned anyway). |
| 1780 + */ |
| 1781 + |
| 1782 +mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b) |
| 1783 +{ |
| 1784 + mp_int tmp; |
| 1785 + mp_err res; |
| 1786 + |
| 1787 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 1788 + |
| 1789 + if((res = mp_init_copy(&tmp, a)) != MP_OKAY) |
| 1790 + return res; |
| 1791 + |
| 1792 + if(SIGN(&tmp) == ZPOS) { |
| 1793 + if((res = s_mp_add_d(&tmp, d)) != MP_OKAY) |
| 1794 + goto CLEANUP; |
| 1795 + } else if(s_mp_cmp_d(&tmp, d) >= 0) { |
| 1796 + if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY) |
| 1797 + goto CLEANUP; |
| 1798 + } else { |
| 1799 + mp_neg(&tmp, &tmp); |
| 1800 + |
| 1801 + DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0); |
| 1802 + } |
| 1803 + |
| 1804 + if(s_mp_cmp_d(&tmp, 0) == 0) |
| 1805 + SIGN(&tmp) = ZPOS; |
| 1806 + |
| 1807 + s_mp_exch(&tmp, b); |
| 1808 + |
| 1809 +CLEANUP: |
| 1810 + mp_clear(&tmp); |
| 1811 + return res; |
| 1812 + |
| 1813 +} /* end mp_add_d() */ |
| 1814 + |
| 1815 +/* }}} */ |
| 1816 + |
| 1817 +/* {{{ mp_sub_d(a, d, b) */ |
| 1818 + |
| 1819 +/* |
| 1820 + mp_sub_d(a, d, b) |
| 1821 + |
| 1822 + Compute the difference b = a - d, for a single digit d. Respects the |
| 1823 + sign of its subtrahend (single digits are unsigned anyway). |
| 1824 + */ |
| 1825 + |
| 1826 +mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b) |
| 1827 +{ |
| 1828 + mp_int tmp; |
| 1829 + mp_err res; |
| 1830 + |
| 1831 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 1832 + |
| 1833 + if((res = mp_init_copy(&tmp, a)) != MP_OKAY) |
| 1834 + return res; |
| 1835 + |
| 1836 + if(SIGN(&tmp) == NEG) { |
| 1837 + if((res = s_mp_add_d(&tmp, d)) != MP_OKAY) |
| 1838 + goto CLEANUP; |
| 1839 + } else if(s_mp_cmp_d(&tmp, d) >= 0) { |
| 1840 + if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY) |
| 1841 + goto CLEANUP; |
| 1842 + } else { |
| 1843 + mp_neg(&tmp, &tmp); |
| 1844 + |
| 1845 + DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0); |
| 1846 + SIGN(&tmp) = NEG; |
| 1847 + } |
| 1848 + |
| 1849 + if(s_mp_cmp_d(&tmp, 0) == 0) |
| 1850 + SIGN(&tmp) = ZPOS; |
| 1851 + |
| 1852 + s_mp_exch(&tmp, b); |
| 1853 + |
| 1854 +CLEANUP: |
| 1855 + mp_clear(&tmp); |
| 1856 + return res; |
| 1857 + |
| 1858 +} /* end mp_sub_d() */ |
| 1859 + |
| 1860 +/* }}} */ |
| 1861 + |
| 1862 +/* {{{ mp_mul_d(a, d, b) */ |
| 1863 + |
| 1864 +/* |
| 1865 + mp_mul_d(a, d, b) |
| 1866 + |
| 1867 + Compute the product b = a * d, for a single digit d. Respects the sign |
| 1868 + of its multiplicand (single digits are unsigned anyway) |
| 1869 + */ |
| 1870 + |
| 1871 +mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b) |
| 1872 +{ |
| 1873 + mp_err res; |
| 1874 + |
| 1875 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 1876 + |
| 1877 + if(d == 0) { |
| 1878 + mp_zero(b); |
| 1879 + return MP_OKAY; |
| 1880 + } |
| 1881 + |
| 1882 + if((res = mp_copy(a, b)) != MP_OKAY) |
| 1883 + return res; |
| 1884 + |
| 1885 + res = s_mp_mul_d(b, d); |
| 1886 + |
| 1887 + return res; |
| 1888 + |
| 1889 +} /* end mp_mul_d() */ |
| 1890 + |
| 1891 +/* }}} */ |
| 1892 + |
| 1893 +/* {{{ mp_mul_2(a, c) */ |
| 1894 + |
| 1895 +mp_err mp_mul_2(const mp_int *a, mp_int *c) |
| 1896 +{ |
| 1897 + mp_err res; |
| 1898 + |
| 1899 + ARGCHK(a != NULL && c != NULL, MP_BADARG); |
| 1900 + |
| 1901 + if((res = mp_copy(a, c)) != MP_OKAY) |
| 1902 + return res; |
| 1903 + |
| 1904 + return s_mp_mul_2(c); |
| 1905 + |
| 1906 +} /* end mp_mul_2() */ |
| 1907 + |
| 1908 +/* }}} */ |
| 1909 + |
| 1910 +/* {{{ mp_div_d(a, d, q, r) */ |
| 1911 + |
| 1912 +/* |
| 1913 + mp_div_d(a, d, q, r) |
| 1914 + |
| 1915 + Compute the quotient q = a / d and remainder r = a mod d, for a |
| 1916 + single digit d. Respects the sign of its divisor (single digits are |
| 1917 + unsigned anyway). |
| 1918 + */ |
| 1919 + |
| 1920 +mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r) |
| 1921 +{ |
| 1922 + mp_err res; |
| 1923 + mp_int qp; |
| 1924 + mp_digit rem; |
| 1925 + int pow; |
| 1926 + |
| 1927 + ARGCHK(a != NULL, MP_BADARG); |
| 1928 + |
| 1929 + if(d == 0) |
| 1930 + return MP_RANGE; |
| 1931 + |
| 1932 + /* Shortcut for powers of two ... */ |
| 1933 + if((pow = s_mp_ispow2d(d)) >= 0) { |
| 1934 + mp_digit mask; |
| 1935 + |
| 1936 + mask = ((mp_digit)1 << pow) - 1; |
| 1937 + rem = DIGIT(a, 0) & mask; |
| 1938 + |
| 1939 + if(q) { |
| 1940 + mp_copy(a, q); |
| 1941 + s_mp_div_2d(q, pow); |
| 1942 + } |
| 1943 + |
| 1944 + if(r) |
| 1945 + *r = rem; |
| 1946 + |
| 1947 + return MP_OKAY; |
| 1948 + } |
| 1949 + |
| 1950 + if((res = mp_init_copy(&qp, a)) != MP_OKAY) |
| 1951 + return res; |
| 1952 + |
| 1953 + res = s_mp_div_d(&qp, d, &rem); |
| 1954 + |
| 1955 + if(s_mp_cmp_d(&qp, 0) == 0) |
| 1956 + SIGN(q) = ZPOS; |
| 1957 + |
| 1958 + if(r) |
| 1959 + *r = rem; |
| 1960 + |
| 1961 + if(q) |
| 1962 + s_mp_exch(&qp, q); |
| 1963 + |
| 1964 + mp_clear(&qp); |
| 1965 + return res; |
| 1966 + |
| 1967 +} /* end mp_div_d() */ |
| 1968 + |
| 1969 +/* }}} */ |
| 1970 + |
| 1971 +/* {{{ mp_div_2(a, c) */ |
| 1972 + |
| 1973 +/* |
| 1974 + mp_div_2(a, c) |
| 1975 + |
| 1976 + Compute c = a / 2, disregarding the remainder. |
| 1977 + */ |
| 1978 + |
| 1979 +mp_err mp_div_2(const mp_int *a, mp_int *c) |
| 1980 +{ |
| 1981 + mp_err res; |
| 1982 + |
| 1983 + ARGCHK(a != NULL && c != NULL, MP_BADARG); |
| 1984 + |
| 1985 + if((res = mp_copy(a, c)) != MP_OKAY) |
| 1986 + return res; |
| 1987 + |
| 1988 + s_mp_div_2(c); |
| 1989 + |
| 1990 + return MP_OKAY; |
| 1991 + |
| 1992 +} /* end mp_div_2() */ |
| 1993 + |
| 1994 +/* }}} */ |
| 1995 + |
| 1996 +/* {{{ mp_expt_d(a, d, b) */ |
| 1997 + |
| 1998 +mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c) |
| 1999 +{ |
| 2000 + mp_int s, x; |
| 2001 + mp_err res; |
| 2002 + |
| 2003 + ARGCHK(a != NULL && c != NULL, MP_BADARG); |
| 2004 + |
| 2005 + if((res = mp_init(&s)) != MP_OKAY) |
| 2006 + return res; |
| 2007 + if((res = mp_init_copy(&x, a)) != MP_OKAY) |
| 2008 + goto X; |
| 2009 + |
| 2010 + DIGIT(&s, 0) = 1; |
| 2011 + |
| 2012 + while(d != 0) { |
| 2013 + if(d & 1) { |
| 2014 + if((res = s_mp_mul(&s, &x)) != MP_OKAY) |
| 2015 + goto CLEANUP; |
| 2016 + } |
| 2017 + |
| 2018 + d /= 2; |
| 2019 + |
| 2020 + if((res = s_mp_sqr(&x)) != MP_OKAY) |
| 2021 + goto CLEANUP; |
| 2022 + } |
| 2023 + |
| 2024 + s_mp_exch(&s, c); |
| 2025 + |
| 2026 +CLEANUP: |
| 2027 + mp_clear(&x); |
| 2028 +X: |
| 2029 + mp_clear(&s); |
| 2030 + |
| 2031 + return res; |
| 2032 + |
| 2033 +} /* end mp_expt_d() */ |
| 2034 + |
| 2035 +/* }}} */ |
| 2036 + |
| 2037 +/* }}} */ |
| 2038 + |
| 2039 +/*------------------------------------------------------------------------*/ |
| 2040 +/* {{{ Full arithmetic */ |
| 2041 + |
| 2042 +/* {{{ mp_abs(a, b) */ |
| 2043 + |
| 2044 +/* |
| 2045 + mp_abs(a, b) |
| 2046 + |
| 2047 + Compute b = |a|. 'a' and 'b' may be identical. |
| 2048 + */ |
| 2049 + |
| 2050 +mp_err mp_abs(const mp_int *a, mp_int *b) |
| 2051 +{ |
| 2052 + mp_err res; |
| 2053 + |
| 2054 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 2055 + |
| 2056 + if((res = mp_copy(a, b)) != MP_OKAY) |
| 2057 + return res; |
| 2058 + |
| 2059 + SIGN(b) = ZPOS; |
| 2060 + |
| 2061 + return MP_OKAY; |
| 2062 + |
| 2063 +} /* end mp_abs() */ |
| 2064 + |
| 2065 +/* }}} */ |
| 2066 + |
| 2067 +/* {{{ mp_neg(a, b) */ |
| 2068 + |
| 2069 +/* |
| 2070 + mp_neg(a, b) |
| 2071 + |
| 2072 + Compute b = -a. 'a' and 'b' may be identical. |
| 2073 + */ |
| 2074 + |
| 2075 +mp_err mp_neg(const mp_int *a, mp_int *b) |
| 2076 +{ |
| 2077 + mp_err res; |
| 2078 + |
| 2079 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 2080 + |
| 2081 + if((res = mp_copy(a, b)) != MP_OKAY) |
| 2082 + return res; |
| 2083 + |
| 2084 + if(s_mp_cmp_d(b, 0) == MP_EQ) |
| 2085 + SIGN(b) = ZPOS; |
| 2086 + else |
| 2087 + SIGN(b) = (SIGN(b) == NEG) ? ZPOS : NEG; |
| 2088 + |
| 2089 + return MP_OKAY; |
| 2090 + |
| 2091 +} /* end mp_neg() */ |
| 2092 + |
| 2093 +/* }}} */ |
| 2094 + |
| 2095 +/* {{{ mp_add(a, b, c) */ |
| 2096 + |
| 2097 +/* |
| 2098 + mp_add(a, b, c) |
| 2099 + |
| 2100 + Compute c = a + b. All parameters may be identical. |
| 2101 + */ |
| 2102 + |
| 2103 +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) |
| 2104 +{ |
| 2105 + mp_err res; |
| 2106 + |
| 2107 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 2108 + |
| 2109 + if(SIGN(a) == SIGN(b)) { /* same sign: add values, keep sign */ |
| 2110 + MP_CHECKOK( s_mp_add_3arg(a, b, c) ); |
| 2111 + } else if(s_mp_cmp(a, b) >= 0) { /* different sign: |a| >= |b| */ |
| 2112 + MP_CHECKOK( s_mp_sub_3arg(a, b, c) ); |
| 2113 + } else { /* different sign: |a| < |b| */ |
| 2114 + MP_CHECKOK( s_mp_sub_3arg(b, a, c) ); |
| 2115 + } |
| 2116 + |
| 2117 + if (s_mp_cmp_d(c, 0) == MP_EQ) |
| 2118 + SIGN(c) = ZPOS; |
| 2119 + |
| 2120 +CLEANUP: |
| 2121 + return res; |
| 2122 + |
| 2123 +} /* end mp_add() */ |
| 2124 + |
| 2125 +/* }}} */ |
| 2126 + |
| 2127 +/* {{{ mp_sub(a, b, c) */ |
| 2128 + |
| 2129 +/* |
| 2130 + mp_sub(a, b, c) |
| 2131 + |
| 2132 + Compute c = a - b. All parameters may be identical. |
| 2133 + */ |
| 2134 + |
| 2135 +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) |
| 2136 +{ |
| 2137 + mp_err res; |
| 2138 + int magDiff; |
| 2139 + |
| 2140 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 2141 + |
| 2142 + if (a == b) { |
| 2143 + mp_zero(c); |
| 2144 + return MP_OKAY; |
| 2145 + } |
| 2146 + |
| 2147 + if (MP_SIGN(a) != MP_SIGN(b)) { |
| 2148 + MP_CHECKOK( s_mp_add_3arg(a, b, c) ); |
| 2149 + } else if (!(magDiff = s_mp_cmp(a, b))) { |
| 2150 + mp_zero(c); |
| 2151 + res = MP_OKAY; |
| 2152 + } else if (magDiff > 0) { |
| 2153 + MP_CHECKOK( s_mp_sub_3arg(a, b, c) ); |
| 2154 + } else { |
| 2155 + MP_CHECKOK( s_mp_sub_3arg(b, a, c) ); |
| 2156 + MP_SIGN(c) = !MP_SIGN(a); |
| 2157 + } |
| 2158 + |
| 2159 + if (s_mp_cmp_d(c, 0) == MP_EQ) |
| 2160 + MP_SIGN(c) = MP_ZPOS; |
| 2161 + |
| 2162 +CLEANUP: |
| 2163 + return res; |
| 2164 + |
| 2165 +} /* end mp_sub() */ |
| 2166 + |
| 2167 +/* }}} */ |
| 2168 + |
| 2169 +/* {{{ mp_mul(a, b, c) */ |
| 2170 + |
| 2171 +/* |
| 2172 + mp_mul(a, b, c) |
| 2173 + |
| 2174 + Compute c = a * b. All parameters may be identical. |
| 2175 + */ |
| 2176 +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int * c) |
| 2177 +{ |
| 2178 + mp_digit *pb; |
| 2179 + mp_int tmp; |
| 2180 + mp_err res; |
| 2181 + mp_size ib; |
| 2182 + mp_size useda, usedb; |
| 2183 + |
| 2184 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 2185 + |
| 2186 + if (a == c) { |
| 2187 + if ((res = mp_init_copy(&tmp, a)) != MP_OKAY) |
| 2188 + return res; |
| 2189 + if (a == b) |
| 2190 + b = &tmp; |
| 2191 + a = &tmp; |
| 2192 + } else if (b == c) { |
| 2193 + if ((res = mp_init_copy(&tmp, b)) != MP_OKAY) |
| 2194 + return res; |
| 2195 + b = &tmp; |
| 2196 + } else { |
| 2197 + MP_DIGITS(&tmp) = 0; |
| 2198 + } |
| 2199 + |
| 2200 + if (MP_USED(a) < MP_USED(b)) { |
| 2201 + const mp_int *xch = b; /* switch a and b, to do fewer outer loops */ |
| 2202 + b = a; |
| 2203 + a = xch; |
| 2204 + } |
| 2205 + |
| 2206 + MP_USED(c) = 1; MP_DIGIT(c, 0) = 0; |
| 2207 + if((res = s_mp_pad(c, USED(a) + USED(b))) != MP_OKAY) |
| 2208 + goto CLEANUP; |
| 2209 + |
| 2210 +#ifdef NSS_USE_COMBA |
| 2211 + if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) { |
| 2212 + if (MP_USED(a) == 4) { |
| 2213 + s_mp_mul_comba_4(a, b, c); |
| 2214 + goto CLEANUP; |
| 2215 + } |
| 2216 + if (MP_USED(a) == 8) { |
| 2217 + s_mp_mul_comba_8(a, b, c); |
| 2218 + goto CLEANUP; |
| 2219 + } |
| 2220 + if (MP_USED(a) == 16) { |
| 2221 + s_mp_mul_comba_16(a, b, c); |
| 2222 + goto CLEANUP; |
| 2223 + } |
| 2224 + if (MP_USED(a) == 32) { |
| 2225 + s_mp_mul_comba_32(a, b, c); |
| 2226 + goto CLEANUP; |
| 2227 + } |
| 2228 + } |
| 2229 +#endif |
| 2230 + |
| 2231 + pb = MP_DIGITS(b); |
| 2232 + s_mpv_mul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c)); |
| 2233 + |
| 2234 + /* Outer loop: Digits of b */ |
| 2235 + useda = MP_USED(a); |
| 2236 + usedb = MP_USED(b); |
| 2237 + for (ib = 1; ib < usedb; ib++) { |
| 2238 + mp_digit b_i = *pb++; |
| 2239 + |
| 2240 + /* Inner product: Digits of a */ |
| 2241 + if (b_i) |
| 2242 + s_mpv_mul_d_add(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib); |
| 2243 + else |
| 2244 + MP_DIGIT(c, ib + useda) = b_i; |
| 2245 + } |
| 2246 + |
| 2247 + s_mp_clamp(c); |
| 2248 + |
| 2249 + if(SIGN(a) == SIGN(b) || s_mp_cmp_d(c, 0) == MP_EQ) |
| 2250 + SIGN(c) = ZPOS; |
| 2251 + else |
| 2252 + SIGN(c) = NEG; |
| 2253 + |
| 2254 +CLEANUP: |
| 2255 + mp_clear(&tmp); |
| 2256 + return res; |
| 2257 +} /* end mp_mul() */ |
| 2258 + |
| 2259 +/* }}} */ |
| 2260 + |
| 2261 +/* {{{ mp_sqr(a, sqr) */ |
| 2262 + |
| 2263 +#if MP_SQUARE |
| 2264 +/* |
| 2265 + Computes the square of a. This can be done more |
| 2266 + efficiently than a general multiplication, because many of the |
| 2267 + computation steps are redundant when squaring. The inner product |
| 2268 + step is a bit more complicated, but we save a fair number of |
| 2269 + iterations of the multiplication loop. |
| 2270 + */ |
| 2271 + |
| 2272 +/* sqr = a^2; Caller provides both a and tmp; */ |
| 2273 +mp_err mp_sqr(const mp_int *a, mp_int *sqr) |
| 2274 +{ |
| 2275 + mp_digit *pa; |
| 2276 + mp_digit d; |
| 2277 + mp_err res; |
| 2278 + mp_size ix; |
| 2279 + mp_int tmp; |
| 2280 + int count; |
| 2281 + |
| 2282 + ARGCHK(a != NULL && sqr != NULL, MP_BADARG); |
| 2283 + |
| 2284 + if (a == sqr) { |
| 2285 + if((res = mp_init_copy(&tmp, a)) != MP_OKAY) |
| 2286 + return res; |
| 2287 + a = &tmp; |
| 2288 + } else { |
| 2289 + DIGITS(&tmp) = 0; |
| 2290 + res = MP_OKAY; |
| 2291 + } |
| 2292 + |
| 2293 + ix = 2 * MP_USED(a); |
| 2294 + if (ix > MP_ALLOC(sqr)) { |
| 2295 + MP_USED(sqr) = 1; |
| 2296 + MP_CHECKOK( s_mp_grow(sqr, ix) ); |
| 2297 + } |
| 2298 + MP_USED(sqr) = ix; |
| 2299 + MP_DIGIT(sqr, 0) = 0; |
| 2300 + |
| 2301 +#ifdef NSS_USE_COMBA |
| 2302 + if (IS_POWER_OF_2(MP_USED(a))) { |
| 2303 + if (MP_USED(a) == 4) { |
| 2304 + s_mp_sqr_comba_4(a, sqr); |
| 2305 + goto CLEANUP; |
| 2306 + } |
| 2307 + if (MP_USED(a) == 8) { |
| 2308 + s_mp_sqr_comba_8(a, sqr); |
| 2309 + goto CLEANUP; |
| 2310 + } |
| 2311 + if (MP_USED(a) == 16) { |
| 2312 + s_mp_sqr_comba_16(a, sqr); |
| 2313 + goto CLEANUP; |
| 2314 + } |
| 2315 + if (MP_USED(a) == 32) { |
| 2316 + s_mp_sqr_comba_32(a, sqr); |
| 2317 + goto CLEANUP; |
| 2318 + } |
| 2319 + } |
| 2320 +#endif |
| 2321 + |
| 2322 + pa = MP_DIGITS(a); |
| 2323 + count = MP_USED(a) - 1; |
| 2324 + if (count > 0) { |
| 2325 + d = *pa++; |
| 2326 + s_mpv_mul_d(pa, count, d, MP_DIGITS(sqr) + 1); |
| 2327 + for (ix = 3; --count > 0; ix += 2) { |
| 2328 + d = *pa++; |
| 2329 + s_mpv_mul_d_add(pa, count, d, MP_DIGITS(sqr) + ix); |
| 2330 + } /* for(ix ...) */ |
| 2331 + MP_DIGIT(sqr, MP_USED(sqr)-1) = 0; /* above loop stopped short of this. */ |
| 2332 + |
| 2333 + /* now sqr *= 2 */ |
| 2334 + s_mp_mul_2(sqr); |
| 2335 + } else { |
| 2336 + MP_DIGIT(sqr, 1) = 0; |
| 2337 + } |
| 2338 + |
| 2339 + /* now add the squares of the digits of a to sqr. */ |
| 2340 + s_mpv_sqr_add_prop(MP_DIGITS(a), MP_USED(a), MP_DIGITS(sqr)); |
| 2341 + |
| 2342 + SIGN(sqr) = ZPOS; |
| 2343 + s_mp_clamp(sqr); |
| 2344 + |
| 2345 +CLEANUP: |
| 2346 + mp_clear(&tmp); |
| 2347 + return res; |
| 2348 + |
| 2349 +} /* end mp_sqr() */ |
| 2350 +#endif |
| 2351 + |
| 2352 +/* }}} */ |
| 2353 + |
| 2354 +/* {{{ mp_div(a, b, q, r) */ |
| 2355 + |
| 2356 +/* |
| 2357 + mp_div(a, b, q, r) |
| 2358 + |
| 2359 + Compute q = a / b and r = a mod b. Input parameters may be re-used |
| 2360 + as output parameters. If q or r is NULL, that portion of the |
| 2361 + computation will be discarded (although it will still be computed) |
| 2362 + */ |
| 2363 +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) |
| 2364 +{ |
| 2365 + mp_err res; |
| 2366 + mp_int *pQ, *pR; |
| 2367 + mp_int qtmp, rtmp, btmp; |
| 2368 + int cmp; |
| 2369 + mp_sign signA; |
| 2370 + mp_sign signB; |
| 2371 + |
| 2372 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 2373 + |
| 2374 + signA = MP_SIGN(a); |
| 2375 + signB = MP_SIGN(b); |
| 2376 + |
| 2377 + if(mp_cmp_z(b) == MP_EQ) |
| 2378 + return MP_RANGE; |
| 2379 + |
| 2380 + DIGITS(&qtmp) = 0; |
| 2381 + DIGITS(&rtmp) = 0; |
| 2382 + DIGITS(&btmp) = 0; |
| 2383 + |
| 2384 + /* Set up some temporaries... */ |
| 2385 + if (!r || r == a || r == b) { |
| 2386 + MP_CHECKOK( mp_init_copy(&rtmp, a) ); |
| 2387 + pR = &rtmp; |
| 2388 + } else { |
| 2389 + MP_CHECKOK( mp_copy(a, r) ); |
| 2390 + pR = r; |
| 2391 + } |
| 2392 + |
| 2393 + if (!q || q == a || q == b) { |
| 2394 + MP_CHECKOK( mp_init_size(&qtmp, MP_USED(a)) ); |
| 2395 + pQ = &qtmp; |
| 2396 + } else { |
| 2397 + MP_CHECKOK( s_mp_pad(q, MP_USED(a)) ); |
| 2398 + pQ = q; |
| 2399 + mp_zero(pQ); |
| 2400 + } |
| 2401 + |
| 2402 + /* |
| 2403 + If |a| <= |b|, we can compute the solution without division; |
| 2404 + otherwise, we actually do the work required. |
| 2405 + */ |
| 2406 + if ((cmp = s_mp_cmp(a, b)) <= 0) { |
| 2407 + if (cmp) { |
| 2408 + /* r was set to a above. */ |
| 2409 + mp_zero(pQ); |
| 2410 + } else { |
| 2411 + mp_set(pQ, 1); |
| 2412 + mp_zero(pR); |
| 2413 + } |
| 2414 + } else { |
| 2415 + MP_CHECKOK( mp_init_copy(&btmp, b) ); |
| 2416 + MP_CHECKOK( s_mp_div(pR, &btmp, pQ) ); |
| 2417 + } |
| 2418 + |
| 2419 + /* Compute the signs for the output */ |
| 2420 + MP_SIGN(pR) = signA; /* Sr = Sa */ |
| 2421 + /* Sq = ZPOS if Sa == Sb */ /* Sq = NEG if Sa != Sb */ |
| 2422 + MP_SIGN(pQ) = (signA == signB) ? ZPOS : NEG; |
| 2423 + |
| 2424 + if(s_mp_cmp_d(pQ, 0) == MP_EQ) |
| 2425 + SIGN(pQ) = ZPOS; |
| 2426 + if(s_mp_cmp_d(pR, 0) == MP_EQ) |
| 2427 + SIGN(pR) = ZPOS; |
| 2428 + |
| 2429 + /* Copy output, if it is needed */ |
| 2430 + if(q && q != pQ) |
| 2431 + s_mp_exch(pQ, q); |
| 2432 + |
| 2433 + if(r && r != pR) |
| 2434 + s_mp_exch(pR, r); |
| 2435 + |
| 2436 +CLEANUP: |
| 2437 + mp_clear(&btmp); |
| 2438 + mp_clear(&rtmp); |
| 2439 + mp_clear(&qtmp); |
| 2440 + |
| 2441 + return res; |
| 2442 + |
| 2443 +} /* end mp_div() */ |
| 2444 + |
| 2445 +/* }}} */ |
| 2446 + |
| 2447 +/* {{{ mp_div_2d(a, d, q, r) */ |
| 2448 + |
| 2449 +mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r) |
| 2450 +{ |
| 2451 + mp_err res; |
| 2452 + |
| 2453 + ARGCHK(a != NULL, MP_BADARG); |
| 2454 + |
| 2455 + if(q) { |
| 2456 + if((res = mp_copy(a, q)) != MP_OKAY) |
| 2457 + return res; |
| 2458 + } |
| 2459 + if(r) { |
| 2460 + if((res = mp_copy(a, r)) != MP_OKAY) |
| 2461 + return res; |
| 2462 + } |
| 2463 + if(q) { |
| 2464 + s_mp_div_2d(q, d); |
| 2465 + } |
| 2466 + if(r) { |
| 2467 + s_mp_mod_2d(r, d); |
| 2468 + } |
| 2469 + |
| 2470 + return MP_OKAY; |
| 2471 + |
| 2472 +} /* end mp_div_2d() */ |
| 2473 + |
| 2474 +/* }}} */ |
| 2475 + |
| 2476 +/* {{{ mp_expt(a, b, c) */ |
| 2477 + |
| 2478 +/* |
| 2479 + mp_expt(a, b, c) |
| 2480 + |
| 2481 + Compute c = a ** b, that is, raise a to the b power. Uses a |
| 2482 + standard iterative square-and-multiply technique. |
| 2483 + */ |
| 2484 + |
| 2485 +mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c) |
| 2486 +{ |
| 2487 + mp_int s, x; |
| 2488 + mp_err res; |
| 2489 + mp_digit d; |
| 2490 + int dig, bit; |
| 2491 + |
| 2492 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 2493 + |
| 2494 + if(mp_cmp_z(b) < 0) |
| 2495 + return MP_RANGE; |
| 2496 + |
| 2497 + if((res = mp_init(&s)) != MP_OKAY) |
| 2498 + return res; |
| 2499 + |
| 2500 + mp_set(&s, 1); |
| 2501 + |
| 2502 + if((res = mp_init_copy(&x, a)) != MP_OKAY) |
| 2503 + goto X; |
| 2504 + |
| 2505 + /* Loop over low-order digits in ascending order */ |
| 2506 + for(dig = 0; dig < (USED(b) - 1); dig++) { |
| 2507 + d = DIGIT(b, dig); |
| 2508 + |
| 2509 + /* Loop over bits of each non-maximal digit */ |
| 2510 + for(bit = 0; bit < DIGIT_BIT; bit++) { |
| 2511 + if(d & 1) { |
| 2512 + if((res = s_mp_mul(&s, &x)) != MP_OKAY) |
| 2513 + goto CLEANUP; |
| 2514 + } |
| 2515 + |
| 2516 + d >>= 1; |
| 2517 + |
| 2518 + if((res = s_mp_sqr(&x)) != MP_OKAY) |
| 2519 + goto CLEANUP; |
| 2520 + } |
| 2521 + } |
| 2522 + |
| 2523 + /* Consider now the last digit... */ |
| 2524 + d = DIGIT(b, dig); |
| 2525 + |
| 2526 + while(d) { |
| 2527 + if(d & 1) { |
| 2528 + if((res = s_mp_mul(&s, &x)) != MP_OKAY) |
| 2529 + goto CLEANUP; |
| 2530 + } |
| 2531 + |
| 2532 + d >>= 1; |
| 2533 + |
| 2534 + if((res = s_mp_sqr(&x)) != MP_OKAY) |
| 2535 + goto CLEANUP; |
| 2536 + } |
| 2537 + |
| 2538 + if(mp_iseven(b)) |
| 2539 + SIGN(&s) = SIGN(a); |
| 2540 + |
| 2541 + res = mp_copy(&s, c); |
| 2542 + |
| 2543 +CLEANUP: |
| 2544 + mp_clear(&x); |
| 2545 +X: |
| 2546 + mp_clear(&s); |
| 2547 + |
| 2548 + return res; |
| 2549 + |
| 2550 +} /* end mp_expt() */ |
| 2551 + |
| 2552 +/* }}} */ |
| 2553 + |
| 2554 +/* {{{ mp_2expt(a, k) */ |
| 2555 + |
| 2556 +/* Compute a = 2^k */ |
| 2557 + |
| 2558 +mp_err mp_2expt(mp_int *a, mp_digit k) |
| 2559 +{ |
| 2560 + ARGCHK(a != NULL, MP_BADARG); |
| 2561 + |
| 2562 + return s_mp_2expt(a, k); |
| 2563 + |
| 2564 +} /* end mp_2expt() */ |
| 2565 + |
| 2566 +/* }}} */ |
| 2567 + |
| 2568 +/* {{{ mp_mod(a, m, c) */ |
| 2569 + |
| 2570 +/* |
| 2571 + mp_mod(a, m, c) |
| 2572 + |
| 2573 + Compute c = a (mod m). Result will always be 0 <= c < m. |
| 2574 + */ |
| 2575 + |
| 2576 +mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c) |
| 2577 +{ |
| 2578 + mp_err res; |
| 2579 + int mag; |
| 2580 + |
| 2581 + ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG); |
| 2582 + |
| 2583 + if(SIGN(m) == NEG) |
| 2584 + return MP_RANGE; |
| 2585 + |
| 2586 + /* |
| 2587 + If |a| > m, we need to divide to get the remainder and take the |
| 2588 + absolute value. |
| 2589 + |
| 2590 + If |a| < m, we don't need to do any division, just copy and adjust |
| 2591 + the sign (if a is negative). |
| 2592 + |
| 2593 + If |a| == m, we can simply set the result to zero. |
| 2594 + |
| 2595 + This order is intended to minimize the average path length of the |
| 2596 + comparison chain on common workloads -- the most frequent cases are |
| 2597 + that |a| != m, so we do those first. |
| 2598 + */ |
| 2599 + if((mag = s_mp_cmp(a, m)) > 0) { |
| 2600 + if((res = mp_div(a, m, NULL, c)) != MP_OKAY) |
| 2601 + return res; |
| 2602 + |
| 2603 + if(SIGN(c) == NEG) { |
| 2604 + if((res = mp_add(c, m, c)) != MP_OKAY) |
| 2605 + return res; |
| 2606 + } |
| 2607 + |
| 2608 + } else if(mag < 0) { |
| 2609 + if((res = mp_copy(a, c)) != MP_OKAY) |
| 2610 + return res; |
| 2611 + |
| 2612 + if(mp_cmp_z(a) < 0) { |
| 2613 + if((res = mp_add(c, m, c)) != MP_OKAY) |
| 2614 + return res; |
| 2615 + |
| 2616 + } |
| 2617 + |
| 2618 + } else { |
| 2619 + mp_zero(c); |
| 2620 + |
| 2621 + } |
| 2622 + |
| 2623 + return MP_OKAY; |
| 2624 + |
| 2625 +} /* end mp_mod() */ |
| 2626 + |
| 2627 +/* }}} */ |
| 2628 + |
| 2629 +/* {{{ mp_mod_d(a, d, c) */ |
| 2630 + |
| 2631 +/* |
| 2632 + mp_mod_d(a, d, c) |
| 2633 + |
| 2634 + Compute c = a (mod d). Result will always be 0 <= c < d |
| 2635 + */ |
| 2636 +mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c) |
| 2637 +{ |
| 2638 + mp_err res; |
| 2639 + mp_digit rem; |
| 2640 + |
| 2641 + ARGCHK(a != NULL && c != NULL, MP_BADARG); |
| 2642 + |
| 2643 + if(s_mp_cmp_d(a, d) > 0) { |
| 2644 + if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY) |
| 2645 + return res; |
| 2646 + |
| 2647 + } else { |
| 2648 + if(SIGN(a) == NEG) |
| 2649 + rem = d - DIGIT(a, 0); |
| 2650 + else |
| 2651 + rem = DIGIT(a, 0); |
| 2652 + } |
| 2653 + |
| 2654 + if(c) |
| 2655 + *c = rem; |
| 2656 + |
| 2657 + return MP_OKAY; |
| 2658 + |
| 2659 +} /* end mp_mod_d() */ |
| 2660 + |
| 2661 +/* }}} */ |
| 2662 + |
| 2663 +/* {{{ mp_sqrt(a, b) */ |
| 2664 + |
| 2665 +/* |
| 2666 + mp_sqrt(a, b) |
| 2667 + |
| 2668 + Compute the integer square root of a, and store the result in b. |
| 2669 + Uses an integer-arithmetic version of Newton's iterative linear |
| 2670 + approximation technique to determine this value; the result has the |
| 2671 + following two properties: |
| 2672 + |
| 2673 + b^2 <= a |
| 2674 + (b+1)^2 >= a |
| 2675 + |
| 2676 + It is a range error to pass a negative value. |
| 2677 + */ |
| 2678 +mp_err mp_sqrt(const mp_int *a, mp_int *b) |
| 2679 +{ |
| 2680 + mp_int x, t; |
| 2681 + mp_err res; |
| 2682 + mp_size used; |
| 2683 + |
| 2684 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 2685 + |
| 2686 + /* Cannot take square root of a negative value */ |
| 2687 + if(SIGN(a) == NEG) |
| 2688 + return MP_RANGE; |
| 2689 + |
| 2690 + /* Special cases for zero and one, trivial */ |
| 2691 + if(mp_cmp_d(a, 1) <= 0) |
| 2692 + return mp_copy(a, b); |
| 2693 + |
| 2694 + /* Initialize the temporaries we'll use below */ |
| 2695 + if((res = mp_init_size(&t, USED(a))) != MP_OKAY) |
| 2696 + return res; |
| 2697 + |
| 2698 + /* Compute an initial guess for the iteration as a itself */ |
| 2699 + if((res = mp_init_copy(&x, a)) != MP_OKAY) |
| 2700 + goto X; |
| 2701 + |
| 2702 + used = MP_USED(&x); |
| 2703 + if (used > 1) { |
| 2704 + s_mp_rshd(&x, used / 2); |
| 2705 + } |
| 2706 + |
| 2707 + for(;;) { |
| 2708 + /* t = (x * x) - a */ |
| 2709 + mp_copy(&x, &t); /* can't fail, t is big enough for original x */ |
| 2710 + if((res = mp_sqr(&t, &t)) != MP_OKAY || |
| 2711 + (res = mp_sub(&t, a, &t)) != MP_OKAY) |
| 2712 + goto CLEANUP; |
| 2713 + |
| 2714 + /* t = t / 2x */ |
| 2715 + s_mp_mul_2(&x); |
| 2716 + if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY) |
| 2717 + goto CLEANUP; |
| 2718 + s_mp_div_2(&x); |
| 2719 + |
| 2720 + /* Terminate the loop, if the quotient is zero */ |
| 2721 + if(mp_cmp_z(&t) == MP_EQ) |
| 2722 + break; |
| 2723 + |
| 2724 + /* x = x - t */ |
| 2725 + if((res = mp_sub(&x, &t, &x)) != MP_OKAY) |
| 2726 + goto CLEANUP; |
| 2727 + |
| 2728 + } |
| 2729 + |
| 2730 + /* Copy result to output parameter */ |
| 2731 + mp_sub_d(&x, 1, &x); |
| 2732 + s_mp_exch(&x, b); |
| 2733 + |
| 2734 + CLEANUP: |
| 2735 + mp_clear(&x); |
| 2736 + X: |
| 2737 + mp_clear(&t); |
| 2738 + |
| 2739 + return res; |
| 2740 + |
| 2741 +} /* end mp_sqrt() */ |
| 2742 + |
| 2743 +/* }}} */ |
| 2744 + |
| 2745 +/* }}} */ |
| 2746 + |
| 2747 +/*------------------------------------------------------------------------*/ |
| 2748 +/* {{{ Modular arithmetic */ |
| 2749 + |
| 2750 +#if MP_MODARITH |
| 2751 +/* {{{ mp_addmod(a, b, m, c) */ |
| 2752 + |
| 2753 +/* |
| 2754 + mp_addmod(a, b, m, c) |
| 2755 + |
| 2756 + Compute c = (a + b) mod m |
| 2757 + */ |
| 2758 + |
| 2759 +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c) |
| 2760 +{ |
| 2761 + mp_err res; |
| 2762 + |
| 2763 + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); |
| 2764 + |
| 2765 + if((res = mp_add(a, b, c)) != MP_OKAY) |
| 2766 + return res; |
| 2767 + if((res = mp_mod(c, m, c)) != MP_OKAY) |
| 2768 + return res; |
| 2769 + |
| 2770 + return MP_OKAY; |
| 2771 + |
| 2772 +} |
| 2773 + |
| 2774 +/* }}} */ |
| 2775 + |
| 2776 +/* {{{ mp_submod(a, b, m, c) */ |
| 2777 + |
| 2778 +/* |
| 2779 + mp_submod(a, b, m, c) |
| 2780 + |
| 2781 + Compute c = (a - b) mod m |
| 2782 + */ |
| 2783 + |
| 2784 +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c) |
| 2785 +{ |
| 2786 + mp_err res; |
| 2787 + |
| 2788 + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); |
| 2789 + |
| 2790 + if((res = mp_sub(a, b, c)) != MP_OKAY) |
| 2791 + return res; |
| 2792 + if((res = mp_mod(c, m, c)) != MP_OKAY) |
| 2793 + return res; |
| 2794 + |
| 2795 + return MP_OKAY; |
| 2796 + |
| 2797 +} |
| 2798 + |
| 2799 +/* }}} */ |
| 2800 + |
| 2801 +/* {{{ mp_mulmod(a, b, m, c) */ |
| 2802 + |
| 2803 +/* |
| 2804 + mp_mulmod(a, b, m, c) |
| 2805 + |
| 2806 + Compute c = (a * b) mod m |
| 2807 + */ |
| 2808 + |
| 2809 +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c) |
| 2810 +{ |
| 2811 + mp_err res; |
| 2812 + |
| 2813 + ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG); |
| 2814 + |
| 2815 + if((res = mp_mul(a, b, c)) != MP_OKAY) |
| 2816 + return res; |
| 2817 + if((res = mp_mod(c, m, c)) != MP_OKAY) |
| 2818 + return res; |
| 2819 + |
| 2820 + return MP_OKAY; |
| 2821 + |
| 2822 +} |
| 2823 + |
| 2824 +/* }}} */ |
| 2825 + |
| 2826 +/* {{{ mp_sqrmod(a, m, c) */ |
| 2827 + |
| 2828 +#if MP_SQUARE |
| 2829 +mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c) |
| 2830 +{ |
| 2831 + mp_err res; |
| 2832 + |
| 2833 + ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG); |
| 2834 + |
| 2835 + if((res = mp_sqr(a, c)) != MP_OKAY) |
| 2836 + return res; |
| 2837 + if((res = mp_mod(c, m, c)) != MP_OKAY) |
| 2838 + return res; |
| 2839 + |
| 2840 + return MP_OKAY; |
| 2841 + |
| 2842 +} /* end mp_sqrmod() */ |
| 2843 +#endif |
| 2844 + |
| 2845 +/* }}} */ |
| 2846 + |
| 2847 +/* {{{ s_mp_exptmod(a, b, m, c) */ |
| 2848 + |
| 2849 +/* |
| 2850 + s_mp_exptmod(a, b, m, c) |
| 2851 + |
| 2852 + Compute c = (a ** b) mod m. Uses a standard square-and-multiply |
| 2853 + method with modular reductions at each step. (This is basically the |
| 2854 + same code as mp_expt(), except for the addition of the reductions) |
| 2855 + |
| 2856 + The modular reductions are done using Barrett's algorithm (see |
| 2857 + s_mp_reduce() below for details) |
| 2858 + */ |
| 2859 + |
| 2860 +mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *
c) |
| 2861 +{ |
| 2862 + mp_int s, x, mu; |
| 2863 + mp_err res; |
| 2864 + mp_digit d; |
| 2865 + int dig, bit; |
| 2866 + |
| 2867 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 2868 + |
| 2869 + if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0) |
| 2870 + return MP_RANGE; |
| 2871 + |
| 2872 + if((res = mp_init(&s)) != MP_OKAY) |
| 2873 + return res; |
| 2874 + if((res = mp_init_copy(&x, a)) != MP_OKAY || |
| 2875 + (res = mp_mod(&x, m, &x)) != MP_OKAY) |
| 2876 + goto X; |
| 2877 + if((res = mp_init(&mu)) != MP_OKAY) |
| 2878 + goto MU; |
| 2879 + |
| 2880 + mp_set(&s, 1); |
| 2881 + |
| 2882 + /* mu = b^2k / m */ |
| 2883 + s_mp_add_d(&mu, 1); |
| 2884 + s_mp_lshd(&mu, 2 * USED(m)); |
| 2885 + if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY) |
| 2886 + goto CLEANUP; |
| 2887 + |
| 2888 + /* Loop over digits of b in ascending order, except highest order */ |
| 2889 + for(dig = 0; dig < (USED(b) - 1); dig++) { |
| 2890 + d = DIGIT(b, dig); |
| 2891 + |
| 2892 + /* Loop over the bits of the lower-order digits */ |
| 2893 + for(bit = 0; bit < DIGIT_BIT; bit++) { |
| 2894 + if(d & 1) { |
| 2895 + if((res = s_mp_mul(&s, &x)) != MP_OKAY) |
| 2896 + goto CLEANUP; |
| 2897 + if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY) |
| 2898 + goto CLEANUP; |
| 2899 + } |
| 2900 + |
| 2901 + d >>= 1; |
| 2902 + |
| 2903 + if((res = s_mp_sqr(&x)) != MP_OKAY) |
| 2904 + goto CLEANUP; |
| 2905 + if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY) |
| 2906 + goto CLEANUP; |
| 2907 + } |
| 2908 + } |
| 2909 + |
| 2910 + /* Now do the last digit... */ |
| 2911 + d = DIGIT(b, dig); |
| 2912 + |
| 2913 + while(d) { |
| 2914 + if(d & 1) { |
| 2915 + if((res = s_mp_mul(&s, &x)) != MP_OKAY) |
| 2916 + goto CLEANUP; |
| 2917 + if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY) |
| 2918 + goto CLEANUP; |
| 2919 + } |
| 2920 + |
| 2921 + d >>= 1; |
| 2922 + |
| 2923 + if((res = s_mp_sqr(&x)) != MP_OKAY) |
| 2924 + goto CLEANUP; |
| 2925 + if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY) |
| 2926 + goto CLEANUP; |
| 2927 + } |
| 2928 + |
| 2929 + s_mp_exch(&s, c); |
| 2930 + |
| 2931 + CLEANUP: |
| 2932 + mp_clear(&mu); |
| 2933 + MU: |
| 2934 + mp_clear(&x); |
| 2935 + X: |
| 2936 + mp_clear(&s); |
| 2937 + |
| 2938 + return res; |
| 2939 + |
| 2940 +} /* end s_mp_exptmod() */ |
| 2941 + |
| 2942 +/* }}} */ |
| 2943 + |
| 2944 +/* {{{ mp_exptmod_d(a, d, m, c) */ |
| 2945 + |
| 2946 +mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c) |
| 2947 +{ |
| 2948 + mp_int s, x; |
| 2949 + mp_err res; |
| 2950 + |
| 2951 + ARGCHK(a != NULL && c != NULL, MP_BADARG); |
| 2952 + |
| 2953 + if((res = mp_init(&s)) != MP_OKAY) |
| 2954 + return res; |
| 2955 + if((res = mp_init_copy(&x, a)) != MP_OKAY) |
| 2956 + goto X; |
| 2957 + |
| 2958 + mp_set(&s, 1); |
| 2959 + |
| 2960 + while(d != 0) { |
| 2961 + if(d & 1) { |
| 2962 + if((res = s_mp_mul(&s, &x)) != MP_OKAY || |
| 2963 + (res = mp_mod(&s, m, &s)) != MP_OKAY) |
| 2964 + goto CLEANUP; |
| 2965 + } |
| 2966 + |
| 2967 + d /= 2; |
| 2968 + |
| 2969 + if((res = s_mp_sqr(&x)) != MP_OKAY || |
| 2970 + (res = mp_mod(&x, m, &x)) != MP_OKAY) |
| 2971 + goto CLEANUP; |
| 2972 + } |
| 2973 + |
| 2974 + s_mp_exch(&s, c); |
| 2975 + |
| 2976 +CLEANUP: |
| 2977 + mp_clear(&x); |
| 2978 +X: |
| 2979 + mp_clear(&s); |
| 2980 + |
| 2981 + return res; |
| 2982 + |
| 2983 +} /* end mp_exptmod_d() */ |
| 2984 + |
| 2985 +/* }}} */ |
| 2986 +#endif /* if MP_MODARITH */ |
| 2987 + |
| 2988 +/* }}} */ |
| 2989 + |
| 2990 +/*------------------------------------------------------------------------*/ |
| 2991 +/* {{{ Comparison functions */ |
| 2992 + |
| 2993 +/* {{{ mp_cmp_z(a) */ |
| 2994 + |
| 2995 +/* |
| 2996 + mp_cmp_z(a) |
| 2997 + |
| 2998 + Compare a <=> 0. Returns <0 if a<0, 0 if a=0, >0 if a>0. |
| 2999 + */ |
| 3000 + |
| 3001 +int mp_cmp_z(const mp_int *a) |
| 3002 +{ |
| 3003 + if(SIGN(a) == NEG) |
| 3004 + return MP_LT; |
| 3005 + else if(USED(a) == 1 && DIGIT(a, 0) == 0) |
| 3006 + return MP_EQ; |
| 3007 + else |
| 3008 + return MP_GT; |
| 3009 + |
| 3010 +} /* end mp_cmp_z() */ |
| 3011 + |
| 3012 +/* }}} */ |
| 3013 + |
| 3014 +/* {{{ mp_cmp_d(a, d) */ |
| 3015 + |
| 3016 +/* |
| 3017 + mp_cmp_d(a, d) |
| 3018 + |
| 3019 + Compare a <=> d. Returns <0 if a<d, 0 if a=d, >0 if a>d |
| 3020 + */ |
| 3021 + |
| 3022 +int mp_cmp_d(const mp_int *a, mp_digit d) |
| 3023 +{ |
| 3024 + ARGCHK(a != NULL, MP_EQ); |
| 3025 + |
| 3026 + if(SIGN(a) == NEG) |
| 3027 + return MP_LT; |
| 3028 + |
| 3029 + return s_mp_cmp_d(a, d); |
| 3030 + |
| 3031 +} /* end mp_cmp_d() */ |
| 3032 + |
| 3033 +/* }}} */ |
| 3034 + |
| 3035 +/* {{{ mp_cmp(a, b) */ |
| 3036 + |
| 3037 +int mp_cmp(const mp_int *a, const mp_int *b) |
| 3038 +{ |
| 3039 + ARGCHK(a != NULL && b != NULL, MP_EQ); |
| 3040 + |
| 3041 + if(SIGN(a) == SIGN(b)) { |
| 3042 + int mag; |
| 3043 + |
| 3044 + if((mag = s_mp_cmp(a, b)) == MP_EQ) |
| 3045 + return MP_EQ; |
| 3046 + |
| 3047 + if(SIGN(a) == ZPOS) |
| 3048 + return mag; |
| 3049 + else |
| 3050 + return -mag; |
| 3051 + |
| 3052 + } else if(SIGN(a) == ZPOS) { |
| 3053 + return MP_GT; |
| 3054 + } else { |
| 3055 + return MP_LT; |
| 3056 + } |
| 3057 + |
| 3058 +} /* end mp_cmp() */ |
| 3059 + |
| 3060 +/* }}} */ |
| 3061 + |
| 3062 +/* {{{ mp_cmp_mag(a, b) */ |
| 3063 + |
| 3064 +/* |
| 3065 + mp_cmp_mag(a, b) |
| 3066 + |
| 3067 + Compares |a| <=> |b|, and returns an appropriate comparison result |
| 3068 + */ |
| 3069 + |
| 3070 +int mp_cmp_mag(mp_int *a, mp_int *b) |
| 3071 +{ |
| 3072 + ARGCHK(a != NULL && b != NULL, MP_EQ); |
| 3073 + |
| 3074 + return s_mp_cmp(a, b); |
| 3075 + |
| 3076 +} /* end mp_cmp_mag() */ |
| 3077 + |
| 3078 +/* }}} */ |
| 3079 + |
| 3080 +/* {{{ mp_cmp_int(a, z) */ |
| 3081 + |
| 3082 +/* |
| 3083 + This just converts z to an mp_int, and uses the existing comparison |
| 3084 + routines. This is sort of inefficient, but it's not clear to me how |
| 3085 + frequently this wil get used anyway. For small positive constants, |
| 3086 + you can always use mp_cmp_d(), and for zero, there is mp_cmp_z(). |
| 3087 + */ |
| 3088 +int mp_cmp_int(const mp_int *a, long z) |
| 3089 +{ |
| 3090 + mp_int tmp; |
| 3091 + int out; |
| 3092 + |
| 3093 + ARGCHK(a != NULL, MP_EQ); |
| 3094 + |
| 3095 + mp_init(&tmp); mp_set_int(&tmp, z); |
| 3096 + out = mp_cmp(a, &tmp); |
| 3097 + mp_clear(&tmp); |
| 3098 + |
| 3099 + return out; |
| 3100 + |
| 3101 +} /* end mp_cmp_int() */ |
| 3102 + |
| 3103 +/* }}} */ |
| 3104 + |
| 3105 +/* {{{ mp_isodd(a) */ |
| 3106 + |
| 3107 +/* |
| 3108 + mp_isodd(a) |
| 3109 + |
| 3110 + Returns a true (non-zero) value if a is odd, false (zero) otherwise. |
| 3111 + */ |
| 3112 +int mp_isodd(const mp_int *a) |
| 3113 +{ |
| 3114 + ARGCHK(a != NULL, 0); |
| 3115 + |
| 3116 + return (int)(DIGIT(a, 0) & 1); |
| 3117 + |
| 3118 +} /* end mp_isodd() */ |
| 3119 + |
| 3120 +/* }}} */ |
| 3121 + |
| 3122 +/* {{{ mp_iseven(a) */ |
| 3123 + |
| 3124 +int mp_iseven(const mp_int *a) |
| 3125 +{ |
| 3126 + return !mp_isodd(a); |
| 3127 + |
| 3128 +} /* end mp_iseven() */ |
| 3129 + |
| 3130 +/* }}} */ |
| 3131 + |
| 3132 +/* }}} */ |
| 3133 + |
| 3134 +/*------------------------------------------------------------------------*/ |
| 3135 +/* {{{ Number theoretic functions */ |
| 3136 + |
| 3137 +#if MP_NUMTH |
| 3138 +/* {{{ mp_gcd(a, b, c) */ |
| 3139 + |
| 3140 +/* |
| 3141 + Like the old mp_gcd() function, except computes the GCD using the |
| 3142 + binary algorithm due to Josef Stein in 1961 (via Knuth). |
| 3143 + */ |
| 3144 +mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c) |
| 3145 +{ |
| 3146 + mp_err res; |
| 3147 + mp_int u, v, t; |
| 3148 + mp_size k = 0; |
| 3149 + |
| 3150 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 3151 + |
| 3152 + if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ) |
| 3153 + return MP_RANGE; |
| 3154 + if(mp_cmp_z(a) == MP_EQ) { |
| 3155 + return mp_copy(b, c); |
| 3156 + } else if(mp_cmp_z(b) == MP_EQ) { |
| 3157 + return mp_copy(a, c); |
| 3158 + } |
| 3159 + |
| 3160 + if((res = mp_init(&t)) != MP_OKAY) |
| 3161 + return res; |
| 3162 + if((res = mp_init_copy(&u, a)) != MP_OKAY) |
| 3163 + goto U; |
| 3164 + if((res = mp_init_copy(&v, b)) != MP_OKAY) |
| 3165 + goto V; |
| 3166 + |
| 3167 + SIGN(&u) = ZPOS; |
| 3168 + SIGN(&v) = ZPOS; |
| 3169 + |
| 3170 + /* Divide out common factors of 2 until at least 1 of a, b is even */ |
| 3171 + while(mp_iseven(&u) && mp_iseven(&v)) { |
| 3172 + s_mp_div_2(&u); |
| 3173 + s_mp_div_2(&v); |
| 3174 + ++k; |
| 3175 + } |
| 3176 + |
| 3177 + /* Initialize t */ |
| 3178 + if(mp_isodd(&u)) { |
| 3179 + if((res = mp_copy(&v, &t)) != MP_OKAY) |
| 3180 + goto CLEANUP; |
| 3181 + |
| 3182 + /* t = -v */ |
| 3183 + if(SIGN(&v) == ZPOS) |
| 3184 + SIGN(&t) = NEG; |
| 3185 + else |
| 3186 + SIGN(&t) = ZPOS; |
| 3187 + |
| 3188 + } else { |
| 3189 + if((res = mp_copy(&u, &t)) != MP_OKAY) |
| 3190 + goto CLEANUP; |
| 3191 + |
| 3192 + } |
| 3193 + |
| 3194 + for(;;) { |
| 3195 + while(mp_iseven(&t)) { |
| 3196 + s_mp_div_2(&t); |
| 3197 + } |
| 3198 + |
| 3199 + if(mp_cmp_z(&t) == MP_GT) { |
| 3200 + if((res = mp_copy(&t, &u)) != MP_OKAY) |
| 3201 + goto CLEANUP; |
| 3202 + |
| 3203 + } else { |
| 3204 + if((res = mp_copy(&t, &v)) != MP_OKAY) |
| 3205 + goto CLEANUP; |
| 3206 + |
| 3207 + /* v = -t */ |
| 3208 + if(SIGN(&t) == ZPOS) |
| 3209 + SIGN(&v) = NEG; |
| 3210 + else |
| 3211 + SIGN(&v) = ZPOS; |
| 3212 + } |
| 3213 + |
| 3214 + if((res = mp_sub(&u, &v, &t)) != MP_OKAY) |
| 3215 + goto CLEANUP; |
| 3216 + |
| 3217 + if(s_mp_cmp_d(&t, 0) == MP_EQ) |
| 3218 + break; |
| 3219 + } |
| 3220 + |
| 3221 + s_mp_2expt(&v, k); /* v = 2^k */ |
| 3222 + res = mp_mul(&u, &v, c); /* c = u * v */ |
| 3223 + |
| 3224 + CLEANUP: |
| 3225 + mp_clear(&v); |
| 3226 + V: |
| 3227 + mp_clear(&u); |
| 3228 + U: |
| 3229 + mp_clear(&t); |
| 3230 + |
| 3231 + return res; |
| 3232 + |
| 3233 +} /* end mp_gcd() */ |
| 3234 + |
| 3235 +/* }}} */ |
| 3236 + |
| 3237 +/* {{{ mp_lcm(a, b, c) */ |
| 3238 + |
| 3239 +/* We compute the least common multiple using the rule: |
| 3240 + |
| 3241 + ab = [a, b](a, b) |
| 3242 + |
| 3243 + ... by computing the product, and dividing out the gcd. |
| 3244 + */ |
| 3245 + |
| 3246 +mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c) |
| 3247 +{ |
| 3248 + mp_int gcd, prod; |
| 3249 + mp_err res; |
| 3250 + |
| 3251 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 3252 + |
| 3253 + /* Set up temporaries */ |
| 3254 + if((res = mp_init(&gcd)) != MP_OKAY) |
| 3255 + return res; |
| 3256 + if((res = mp_init(&prod)) != MP_OKAY) |
| 3257 + goto GCD; |
| 3258 + |
| 3259 + if((res = mp_mul(a, b, &prod)) != MP_OKAY) |
| 3260 + goto CLEANUP; |
| 3261 + if((res = mp_gcd(a, b, &gcd)) != MP_OKAY) |
| 3262 + goto CLEANUP; |
| 3263 + |
| 3264 + res = mp_div(&prod, &gcd, c, NULL); |
| 3265 + |
| 3266 + CLEANUP: |
| 3267 + mp_clear(&prod); |
| 3268 + GCD: |
| 3269 + mp_clear(&gcd); |
| 3270 + |
| 3271 + return res; |
| 3272 + |
| 3273 +} /* end mp_lcm() */ |
| 3274 + |
| 3275 +/* }}} */ |
| 3276 + |
| 3277 +/* {{{ mp_xgcd(a, b, g, x, y) */ |
| 3278 + |
| 3279 +/* |
| 3280 + mp_xgcd(a, b, g, x, y) |
| 3281 + |
| 3282 + Compute g = (a, b) and values x and y satisfying Bezout's identity |
| 3283 + (that is, ax + by = g). This uses the binary extended GCD algorithm |
| 3284 + based on the Stein algorithm used for mp_gcd() |
| 3285 + See algorithm 14.61 in Handbook of Applied Cryptogrpahy. |
| 3286 + */ |
| 3287 + |
| 3288 +mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *
y) |
| 3289 +{ |
| 3290 + mp_int gx, xc, yc, u, v, A, B, C, D; |
| 3291 + mp_int *clean[9]; |
| 3292 + mp_err res; |
| 3293 + int last = -1; |
| 3294 + |
| 3295 + if(mp_cmp_z(b) == 0) |
| 3296 + return MP_RANGE; |
| 3297 + |
| 3298 + /* Initialize all these variables we need */ |
| 3299 + MP_CHECKOK( mp_init(&u) ); |
| 3300 + clean[++last] = &u; |
| 3301 + MP_CHECKOK( mp_init(&v) ); |
| 3302 + clean[++last] = &v; |
| 3303 + MP_CHECKOK( mp_init(&gx) ); |
| 3304 + clean[++last] = &gx; |
| 3305 + MP_CHECKOK( mp_init(&A) ); |
| 3306 + clean[++last] = &A; |
| 3307 + MP_CHECKOK( mp_init(&B) ); |
| 3308 + clean[++last] = &B; |
| 3309 + MP_CHECKOK( mp_init(&C) ); |
| 3310 + clean[++last] = &C; |
| 3311 + MP_CHECKOK( mp_init(&D) ); |
| 3312 + clean[++last] = &D; |
| 3313 + MP_CHECKOK( mp_init_copy(&xc, a) ); |
| 3314 + clean[++last] = &xc; |
| 3315 + mp_abs(&xc, &xc); |
| 3316 + MP_CHECKOK( mp_init_copy(&yc, b) ); |
| 3317 + clean[++last] = &yc; |
| 3318 + mp_abs(&yc, &yc); |
| 3319 + |
| 3320 + mp_set(&gx, 1); |
| 3321 + |
| 3322 + /* Divide by two until at least one of them is odd */ |
| 3323 + while(mp_iseven(&xc) && mp_iseven(&yc)) { |
| 3324 + mp_size nx = mp_trailing_zeros(&xc); |
| 3325 + mp_size ny = mp_trailing_zeros(&yc); |
| 3326 + mp_size n = MP_MIN(nx, ny); |
| 3327 + s_mp_div_2d(&xc,n); |
| 3328 + s_mp_div_2d(&yc,n); |
| 3329 + MP_CHECKOK( s_mp_mul_2d(&gx,n) ); |
| 3330 + } |
| 3331 + |
| 3332 + mp_copy(&xc, &u); |
| 3333 + mp_copy(&yc, &v); |
| 3334 + mp_set(&A, 1); mp_set(&D, 1); |
| 3335 + |
| 3336 + /* Loop through binary GCD algorithm */ |
| 3337 + do { |
| 3338 + while(mp_iseven(&u)) { |
| 3339 + s_mp_div_2(&u); |
| 3340 + |
| 3341 + if(mp_iseven(&A) && mp_iseven(&B)) { |
| 3342 + s_mp_div_2(&A); s_mp_div_2(&B); |
| 3343 + } else { |
| 3344 + MP_CHECKOK( mp_add(&A, &yc, &A) ); |
| 3345 + s_mp_div_2(&A); |
| 3346 + MP_CHECKOK( mp_sub(&B, &xc, &B) ); |
| 3347 + s_mp_div_2(&B); |
| 3348 + } |
| 3349 + } |
| 3350 + |
| 3351 + while(mp_iseven(&v)) { |
| 3352 + s_mp_div_2(&v); |
| 3353 + |
| 3354 + if(mp_iseven(&C) && mp_iseven(&D)) { |
| 3355 + s_mp_div_2(&C); s_mp_div_2(&D); |
| 3356 + } else { |
| 3357 + MP_CHECKOK( mp_add(&C, &yc, &C) ); |
| 3358 + s_mp_div_2(&C); |
| 3359 + MP_CHECKOK( mp_sub(&D, &xc, &D) ); |
| 3360 + s_mp_div_2(&D); |
| 3361 + } |
| 3362 + } |
| 3363 + |
| 3364 + if(mp_cmp(&u, &v) >= 0) { |
| 3365 + MP_CHECKOK( mp_sub(&u, &v, &u) ); |
| 3366 + MP_CHECKOK( mp_sub(&A, &C, &A) ); |
| 3367 + MP_CHECKOK( mp_sub(&B, &D, &B) ); |
| 3368 + } else { |
| 3369 + MP_CHECKOK( mp_sub(&v, &u, &v) ); |
| 3370 + MP_CHECKOK( mp_sub(&C, &A, &C) ); |
| 3371 + MP_CHECKOK( mp_sub(&D, &B, &D) ); |
| 3372 + } |
| 3373 + } while (mp_cmp_z(&u) != 0); |
| 3374 + |
| 3375 + /* copy results to output */ |
| 3376 + if(x) |
| 3377 + MP_CHECKOK( mp_copy(&C, x) ); |
| 3378 + |
| 3379 + if(y) |
| 3380 + MP_CHECKOK( mp_copy(&D, y) ); |
| 3381 + |
| 3382 + if(g) |
| 3383 + MP_CHECKOK( mp_mul(&gx, &v, g) ); |
| 3384 + |
| 3385 + CLEANUP: |
| 3386 + while(last >= 0) |
| 3387 + mp_clear(clean[last--]); |
| 3388 + |
| 3389 + return res; |
| 3390 + |
| 3391 +} /* end mp_xgcd() */ |
| 3392 + |
| 3393 +/* }}} */ |
| 3394 + |
| 3395 +mp_size mp_trailing_zeros(const mp_int *mp) |
| 3396 +{ |
| 3397 + mp_digit d; |
| 3398 + mp_size n = 0; |
| 3399 + int ix; |
| 3400 + |
| 3401 + if (!mp || !MP_DIGITS(mp) || !mp_cmp_z(mp)) |
| 3402 + return n; |
| 3403 + |
| 3404 + for (ix = 0; !(d = MP_DIGIT(mp,ix)) && (ix < MP_USED(mp)); ++ix) |
| 3405 + n += MP_DIGIT_BIT; |
| 3406 + if (!d) |
| 3407 + return 0; /* shouldn't happen, but ... */ |
| 3408 +#if !defined(MP_USE_UINT_DIGIT) |
| 3409 + if (!(d & 0xffffffffU)) { |
| 3410 + d >>= 32; |
| 3411 + n += 32; |
| 3412 + } |
| 3413 +#endif |
| 3414 + if (!(d & 0xffffU)) { |
| 3415 + d >>= 16; |
| 3416 + n += 16; |
| 3417 + } |
| 3418 + if (!(d & 0xffU)) { |
| 3419 + d >>= 8; |
| 3420 + n += 8; |
| 3421 + } |
| 3422 + if (!(d & 0xfU)) { |
| 3423 + d >>= 4; |
| 3424 + n += 4; |
| 3425 + } |
| 3426 + if (!(d & 0x3U)) { |
| 3427 + d >>= 2; |
| 3428 + n += 2; |
| 3429 + } |
| 3430 + if (!(d & 0x1U)) { |
| 3431 + d >>= 1; |
| 3432 + n += 1; |
| 3433 + } |
| 3434 +#if MP_ARGCHK == 2 |
| 3435 + assert(0 != (d & 1)); |
| 3436 +#endif |
| 3437 + return n; |
| 3438 +} |
| 3439 + |
| 3440 +/* Given a and prime p, computes c and k such that a*c == 2**k (mod p). |
| 3441 +** Returns k (positive) or error (negative). |
| 3442 +** This technique from the paper "Fast Modular Reciprocals" (unpublished) |
| 3443 +** by Richard Schroeppel (a.k.a. Captain Nemo). |
| 3444 +*/ |
| 3445 +mp_err s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c) |
| 3446 +{ |
| 3447 + mp_err res; |
| 3448 + mp_err k = 0; |
| 3449 + mp_int d, f, g; |
| 3450 + |
| 3451 + ARGCHK(a && p && c, MP_BADARG); |
| 3452 + |
| 3453 + MP_DIGITS(&d) = 0; |
| 3454 + MP_DIGITS(&f) = 0; |
| 3455 + MP_DIGITS(&g) = 0; |
| 3456 + MP_CHECKOK( mp_init(&d) ); |
| 3457 + MP_CHECKOK( mp_init_copy(&f, a) ); /* f = a */ |
| 3458 + MP_CHECKOK( mp_init_copy(&g, p) ); /* g = p */ |
| 3459 + |
| 3460 + mp_set(c, 1); |
| 3461 + mp_zero(&d); |
| 3462 + |
| 3463 + if (mp_cmp_z(&f) == 0) { |
| 3464 + res = MP_UNDEF; |
| 3465 + } else |
| 3466 + for (;;) { |
| 3467 + int diff_sign; |
| 3468 + while (mp_iseven(&f)) { |
| 3469 + mp_size n = mp_trailing_zeros(&f); |
| 3470 + if (!n) { |
| 3471 + res = MP_UNDEF; |
| 3472 + goto CLEANUP; |
| 3473 + } |
| 3474 + s_mp_div_2d(&f, n); |
| 3475 + MP_CHECKOK( s_mp_mul_2d(&d, n) ); |
| 3476 + k += n; |
| 3477 + } |
| 3478 + if (mp_cmp_d(&f, 1) == MP_EQ) { /* f == 1 */ |
| 3479 + res = k; |
| 3480 + break; |
| 3481 + } |
| 3482 + diff_sign = mp_cmp(&f, &g); |
| 3483 + if (diff_sign < 0) { /* f < g */ |
| 3484 + s_mp_exch(&f, &g); |
| 3485 + s_mp_exch(c, &d); |
| 3486 + } else if (diff_sign == 0) { /* f == g */ |
| 3487 + res = MP_UNDEF; /* a and p are not relatively prime */ |
| 3488 + break; |
| 3489 + } |
| 3490 + if ((MP_DIGIT(&f,0) % 4) == (MP_DIGIT(&g,0) % 4)) { |
| 3491 + MP_CHECKOK( mp_sub(&f, &g, &f) ); /* f = f - g */ |
| 3492 + MP_CHECKOK( mp_sub(c, &d, c) ); /* c = c - d */ |
| 3493 + } else { |
| 3494 + MP_CHECKOK( mp_add(&f, &g, &f) ); /* f = f + g */ |
| 3495 + MP_CHECKOK( mp_add(c, &d, c) ); /* c = c + d */ |
| 3496 + } |
| 3497 + } |
| 3498 + if (res >= 0) { |
| 3499 + while (MP_SIGN(c) != MP_ZPOS) { |
| 3500 + MP_CHECKOK( mp_add(c, p, c) ); |
| 3501 + } |
| 3502 + res = k; |
| 3503 + } |
| 3504 + |
| 3505 +CLEANUP: |
| 3506 + mp_clear(&d); |
| 3507 + mp_clear(&f); |
| 3508 + mp_clear(&g); |
| 3509 + return res; |
| 3510 +} |
| 3511 + |
| 3512 +/* Compute T = (P ** -1) mod MP_RADIX. Also works for 16-bit mp_digits. |
| 3513 +** This technique from the paper "Fast Modular Reciprocals" (unpublished) |
| 3514 +** by Richard Schroeppel (a.k.a. Captain Nemo). |
| 3515 +*/ |
| 3516 +mp_digit s_mp_invmod_radix(mp_digit P) |
| 3517 +{ |
| 3518 + mp_digit T = P; |
| 3519 + T *= 2 - (P * T); |
| 3520 + T *= 2 - (P * T); |
| 3521 + T *= 2 - (P * T); |
| 3522 + T *= 2 - (P * T); |
| 3523 +#if !defined(MP_USE_UINT_DIGIT) |
| 3524 + T *= 2 - (P * T); |
| 3525 + T *= 2 - (P * T); |
| 3526 +#endif |
| 3527 + return T; |
| 3528 +} |
| 3529 + |
| 3530 +/* Given c, k, and prime p, where a*c == 2**k (mod p), |
| 3531 +** Compute x = (a ** -1) mod p. This is similar to Montgomery reduction. |
| 3532 +** This technique from the paper "Fast Modular Reciprocals" (unpublished) |
| 3533 +** by Richard Schroeppel (a.k.a. Captain Nemo). |
| 3534 +*/ |
| 3535 +mp_err s_mp_fixup_reciprocal(const mp_int *c, const mp_int *p, int k, mp_int *
x) |
| 3536 +{ |
| 3537 + int k_orig = k; |
| 3538 + mp_digit r; |
| 3539 + mp_size ix; |
| 3540 + mp_err res; |
| 3541 + |
| 3542 + if (mp_cmp_z(c) < 0) { /* c < 0 */ |
| 3543 + MP_CHECKOK( mp_add(c, p, x) ); /* x = c + p */ |
| 3544 + } else { |
| 3545 + MP_CHECKOK( mp_copy(c, x) ); /* x = c */ |
| 3546 + } |
| 3547 + |
| 3548 + /* make sure x is large enough */ |
| 3549 + ix = MP_HOWMANY(k, MP_DIGIT_BIT) + MP_USED(p) + 1; |
| 3550 + ix = MP_MAX(ix, MP_USED(x)); |
| 3551 + MP_CHECKOK( s_mp_pad(x, ix) ); |
| 3552 + |
| 3553 + r = 0 - s_mp_invmod_radix(MP_DIGIT(p,0)); |
| 3554 + |
| 3555 + for (ix = 0; k > 0; ix++) { |
| 3556 + int j = MP_MIN(k, MP_DIGIT_BIT); |
| 3557 + mp_digit v = r * MP_DIGIT(x, ix); |
| 3558 + if (j < MP_DIGIT_BIT) { |
| 3559 + v &= ((mp_digit)1 << j) - 1; /* v = v mod (2 ** j) */ |
| 3560 + } |
| 3561 + s_mp_mul_d_add_offset(p, v, x, ix); /* x += p * v * (RADIX ** ix) */ |
| 3562 + k -= j; |
| 3563 + } |
| 3564 + s_mp_clamp(x); |
| 3565 + s_mp_div_2d(x, k_orig); |
| 3566 + res = MP_OKAY; |
| 3567 + |
| 3568 +CLEANUP: |
| 3569 + return res; |
| 3570 +} |
| 3571 + |
| 3572 +/* compute mod inverse using Schroeppel's method, only if m is odd */ |
| 3573 +mp_err s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c) |
| 3574 +{ |
| 3575 + int k; |
| 3576 + mp_err res; |
| 3577 + mp_int x; |
| 3578 + |
| 3579 + ARGCHK(a && m && c, MP_BADARG); |
| 3580 + |
| 3581 + if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0) |
| 3582 + return MP_RANGE; |
| 3583 + if (mp_iseven(m)) |
| 3584 + return MP_UNDEF; |
| 3585 + |
| 3586 + MP_DIGITS(&x) = 0; |
| 3587 + |
| 3588 + if (a == c) { |
| 3589 + if ((res = mp_init_copy(&x, a)) != MP_OKAY) |
| 3590 + return res; |
| 3591 + if (a == m) |
| 3592 + m = &x; |
| 3593 + a = &x; |
| 3594 + } else if (m == c) { |
| 3595 + if ((res = mp_init_copy(&x, m)) != MP_OKAY) |
| 3596 + return res; |
| 3597 + m = &x; |
| 3598 + } else { |
| 3599 + MP_DIGITS(&x) = 0; |
| 3600 + } |
| 3601 + |
| 3602 + MP_CHECKOK( s_mp_almost_inverse(a, m, c) ); |
| 3603 + k = res; |
| 3604 + MP_CHECKOK( s_mp_fixup_reciprocal(c, m, k, c) ); |
| 3605 +CLEANUP: |
| 3606 + mp_clear(&x); |
| 3607 + return res; |
| 3608 +} |
| 3609 + |
| 3610 +/* Known good algorithm for computing modular inverse. But slow. */ |
| 3611 +mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c) |
| 3612 +{ |
| 3613 + mp_int g, x; |
| 3614 + mp_err res; |
| 3615 + |
| 3616 + ARGCHK(a && m && c, MP_BADARG); |
| 3617 + |
| 3618 + if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0) |
| 3619 + return MP_RANGE; |
| 3620 + |
| 3621 + MP_DIGITS(&g) = 0; |
| 3622 + MP_DIGITS(&x) = 0; |
| 3623 + MP_CHECKOK( mp_init(&x) ); |
| 3624 + MP_CHECKOK( mp_init(&g) ); |
| 3625 + |
| 3626 + MP_CHECKOK( mp_xgcd(a, m, &g, &x, NULL) ); |
| 3627 + |
| 3628 + if (mp_cmp_d(&g, 1) != MP_EQ) { |
| 3629 + res = MP_UNDEF; |
| 3630 + goto CLEANUP; |
| 3631 + } |
| 3632 + |
| 3633 + res = mp_mod(&x, m, c); |
| 3634 + SIGN(c) = SIGN(a); |
| 3635 + |
| 3636 +CLEANUP: |
| 3637 + mp_clear(&x); |
| 3638 + mp_clear(&g); |
| 3639 + |
| 3640 + return res; |
| 3641 +} |
| 3642 + |
| 3643 +/* modular inverse where modulus is 2**k. */ |
| 3644 +/* c = a**-1 mod 2**k */ |
| 3645 +mp_err s_mp_invmod_2d(const mp_int *a, mp_size k, mp_int *c) |
| 3646 +{ |
| 3647 + mp_err res; |
| 3648 + mp_size ix = k + 4; |
| 3649 + mp_int t0, t1, val, tmp, two2k; |
| 3650 + |
| 3651 + static const mp_digit d2 = 2; |
| 3652 + static const mp_int two = { MP_ZPOS, 1, 1, (mp_digit *)&d2 }; |
| 3653 + |
| 3654 + if (mp_iseven(a)) |
| 3655 + return MP_UNDEF; |
| 3656 + if (k <= MP_DIGIT_BIT) { |
| 3657 + mp_digit i = s_mp_invmod_radix(MP_DIGIT(a,0)); |
| 3658 + if (k < MP_DIGIT_BIT) |
| 3659 + i &= ((mp_digit)1 << k) - (mp_digit)1; |
| 3660 + mp_set(c, i); |
| 3661 + return MP_OKAY; |
| 3662 + } |
| 3663 + MP_DIGITS(&t0) = 0; |
| 3664 + MP_DIGITS(&t1) = 0; |
| 3665 + MP_DIGITS(&val) = 0; |
| 3666 + MP_DIGITS(&tmp) = 0; |
| 3667 + MP_DIGITS(&two2k) = 0; |
| 3668 + MP_CHECKOK( mp_init_copy(&val, a) ); |
| 3669 + s_mp_mod_2d(&val, k); |
| 3670 + MP_CHECKOK( mp_init_copy(&t0, &val) ); |
| 3671 + MP_CHECKOK( mp_init_copy(&t1, &t0) ); |
| 3672 + MP_CHECKOK( mp_init(&tmp) ); |
| 3673 + MP_CHECKOK( mp_init(&two2k) ); |
| 3674 + MP_CHECKOK( s_mp_2expt(&two2k, k) ); |
| 3675 + do { |
| 3676 + MP_CHECKOK( mp_mul(&val, &t1, &tmp) ); |
| 3677 + MP_CHECKOK( mp_sub(&two, &tmp, &tmp) ); |
| 3678 + MP_CHECKOK( mp_mul(&t1, &tmp, &t1) ); |
| 3679 + s_mp_mod_2d(&t1, k); |
| 3680 + while (MP_SIGN(&t1) != MP_ZPOS) { |
| 3681 + MP_CHECKOK( mp_add(&t1, &two2k, &t1) ); |
| 3682 + } |
| 3683 + if (mp_cmp(&t1, &t0) == MP_EQ) |
| 3684 + break; |
| 3685 + MP_CHECKOK( mp_copy(&t1, &t0) ); |
| 3686 + } while (--ix > 0); |
| 3687 + if (!ix) { |
| 3688 + res = MP_UNDEF; |
| 3689 + } else { |
| 3690 + mp_exch(c, &t1); |
| 3691 + } |
| 3692 + |
| 3693 +CLEANUP: |
| 3694 + mp_clear(&t0); |
| 3695 + mp_clear(&t1); |
| 3696 + mp_clear(&val); |
| 3697 + mp_clear(&tmp); |
| 3698 + mp_clear(&two2k); |
| 3699 + return res; |
| 3700 +} |
| 3701 + |
| 3702 +mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c) |
| 3703 +{ |
| 3704 + mp_err res; |
| 3705 + mp_size k; |
| 3706 + mp_int oddFactor, evenFactor; /* factors of the modulus */ |
| 3707 + mp_int oddPart, evenPart; /* parts to combine via CRT. */ |
| 3708 + mp_int C2, tmp1, tmp2; |
| 3709 + |
| 3710 + /*static const mp_digit d1 = 1; */ |
| 3711 + /*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */ |
| 3712 + |
| 3713 + if ((res = s_mp_ispow2(m)) >= 0) { |
| 3714 + k = res; |
| 3715 + return s_mp_invmod_2d(a, k, c); |
| 3716 + } |
| 3717 + MP_DIGITS(&oddFactor) = 0; |
| 3718 + MP_DIGITS(&evenFactor) = 0; |
| 3719 + MP_DIGITS(&oddPart) = 0; |
| 3720 + MP_DIGITS(&evenPart) = 0; |
| 3721 + MP_DIGITS(&C2) = 0; |
| 3722 + MP_DIGITS(&tmp1) = 0; |
| 3723 + MP_DIGITS(&tmp2) = 0; |
| 3724 + |
| 3725 + MP_CHECKOK( mp_init_copy(&oddFactor, m) ); /* oddFactor = m */ |
| 3726 + MP_CHECKOK( mp_init(&evenFactor) ); |
| 3727 + MP_CHECKOK( mp_init(&oddPart) ); |
| 3728 + MP_CHECKOK( mp_init(&evenPart) ); |
| 3729 + MP_CHECKOK( mp_init(&C2) ); |
| 3730 + MP_CHECKOK( mp_init(&tmp1) ); |
| 3731 + MP_CHECKOK( mp_init(&tmp2) ); |
| 3732 + |
| 3733 + k = mp_trailing_zeros(m); |
| 3734 + s_mp_div_2d(&oddFactor, k); |
| 3735 + MP_CHECKOK( s_mp_2expt(&evenFactor, k) ); |
| 3736 + |
| 3737 + /* compute a**-1 mod oddFactor. */ |
| 3738 + MP_CHECKOK( s_mp_invmod_odd_m(a, &oddFactor, &oddPart) ); |
| 3739 + /* compute a**-1 mod evenFactor, where evenFactor == 2**k. */ |
| 3740 + MP_CHECKOK( s_mp_invmod_2d( a, k, &evenPart) ); |
| 3741 + |
| 3742 + /* Use Chinese Remainer theorem to compute a**-1 mod m. */ |
| 3743 + /* let m1 = oddFactor, v1 = oddPart, |
| 3744 + * let m2 = evenFactor, v2 = evenPart. |
| 3745 + */ |
| 3746 + |
| 3747 + /* Compute C2 = m1**-1 mod m2. */ |
| 3748 + MP_CHECKOK( s_mp_invmod_2d(&oddFactor, k, &C2) ); |
| 3749 + |
| 3750 + /* compute u = (v2 - v1)*C2 mod m2 */ |
| 3751 + MP_CHECKOK( mp_sub(&evenPart, &oddPart, &tmp1) ); |
| 3752 + MP_CHECKOK( mp_mul(&tmp1, &C2, &tmp2) ); |
| 3753 + s_mp_mod_2d(&tmp2, k); |
| 3754 + while (MP_SIGN(&tmp2) != MP_ZPOS) { |
| 3755 + MP_CHECKOK( mp_add(&tmp2, &evenFactor, &tmp2) ); |
| 3756 + } |
| 3757 + |
| 3758 + /* compute answer = v1 + u*m1 */ |
| 3759 + MP_CHECKOK( mp_mul(&tmp2, &oddFactor, c) ); |
| 3760 + MP_CHECKOK( mp_add(&oddPart, c, c) ); |
| 3761 + /* not sure this is necessary, but it's low cost if not. */ |
| 3762 + MP_CHECKOK( mp_mod(c, m, c) ); |
| 3763 + |
| 3764 +CLEANUP: |
| 3765 + mp_clear(&oddFactor); |
| 3766 + mp_clear(&evenFactor); |
| 3767 + mp_clear(&oddPart); |
| 3768 + mp_clear(&evenPart); |
| 3769 + mp_clear(&C2); |
| 3770 + mp_clear(&tmp1); |
| 3771 + mp_clear(&tmp2); |
| 3772 + return res; |
| 3773 +} |
| 3774 + |
| 3775 + |
| 3776 +/* {{{ mp_invmod(a, m, c) */ |
| 3777 + |
| 3778 +/* |
| 3779 + mp_invmod(a, m, c) |
| 3780 + |
| 3781 + Compute c = a^-1 (mod m), if there is an inverse for a (mod m). |
| 3782 + This is equivalent to the question of whether (a, m) = 1. If not, |
| 3783 + MP_UNDEF is returned, and there is no inverse. |
| 3784 + */ |
| 3785 + |
| 3786 +mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c) |
| 3787 +{ |
| 3788 + |
| 3789 + ARGCHK(a && m && c, MP_BADARG); |
| 3790 + |
| 3791 + if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0) |
| 3792 + return MP_RANGE; |
| 3793 + |
| 3794 + if (mp_isodd(m)) { |
| 3795 + return s_mp_invmod_odd_m(a, m, c); |
| 3796 + } |
| 3797 + if (mp_iseven(a)) |
| 3798 + return MP_UNDEF; /* not invertable */ |
| 3799 + |
| 3800 + return s_mp_invmod_even_m(a, m, c); |
| 3801 + |
| 3802 +} /* end mp_invmod() */ |
| 3803 + |
| 3804 +/* }}} */ |
| 3805 +#endif /* if MP_NUMTH */ |
| 3806 + |
| 3807 +/* }}} */ |
| 3808 + |
| 3809 +/*------------------------------------------------------------------------*/ |
| 3810 +/* {{{ mp_print(mp, ofp) */ |
| 3811 + |
| 3812 +#if MP_IOFUNC |
| 3813 +/* |
| 3814 + mp_print(mp, ofp) |
| 3815 + |
| 3816 + Print a textual representation of the given mp_int on the output |
| 3817 + stream 'ofp'. Output is generated using the internal radix. |
| 3818 + */ |
| 3819 + |
| 3820 +void mp_print(mp_int *mp, FILE *ofp) |
| 3821 +{ |
| 3822 + int ix; |
| 3823 + |
| 3824 + if(mp == NULL || ofp == NULL) |
| 3825 + return; |
| 3826 + |
| 3827 + fputc((SIGN(mp) == NEG) ? '-' : '+', ofp); |
| 3828 + |
| 3829 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 3830 + fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix)); |
| 3831 + } |
| 3832 + |
| 3833 +} /* end mp_print() */ |
| 3834 + |
| 3835 +#endif /* if MP_IOFUNC */ |
| 3836 + |
| 3837 +/* }}} */ |
| 3838 + |
| 3839 +/*------------------------------------------------------------------------*/ |
| 3840 +/* {{{ More I/O Functions */ |
| 3841 + |
| 3842 +/* {{{ mp_read_raw(mp, str, len) */ |
| 3843 + |
| 3844 +/* |
| 3845 + mp_read_raw(mp, str, len) |
| 3846 + |
| 3847 + Read in a raw value (base 256) into the given mp_int |
| 3848 + */ |
| 3849 + |
| 3850 +mp_err mp_read_raw(mp_int *mp, char *str, int len) |
| 3851 +{ |
| 3852 + int ix; |
| 3853 + mp_err res; |
| 3854 + unsigned char *ustr = (unsigned char *)str; |
| 3855 + |
| 3856 + ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG); |
| 3857 + |
| 3858 + mp_zero(mp); |
| 3859 + |
| 3860 + /* Get sign from first byte */ |
| 3861 + if(ustr[0]) |
| 3862 + SIGN(mp) = NEG; |
| 3863 + else |
| 3864 + SIGN(mp) = ZPOS; |
| 3865 + |
| 3866 + /* Read the rest of the digits */ |
| 3867 + for(ix = 1; ix < len; ix++) { |
| 3868 + if((res = mp_mul_d(mp, 256, mp)) != MP_OKAY) |
| 3869 + return res; |
| 3870 + if((res = mp_add_d(mp, ustr[ix], mp)) != MP_OKAY) |
| 3871 + return res; |
| 3872 + } |
| 3873 + |
| 3874 + return MP_OKAY; |
| 3875 + |
| 3876 +} /* end mp_read_raw() */ |
| 3877 + |
| 3878 +/* }}} */ |
| 3879 + |
| 3880 +/* {{{ mp_raw_size(mp) */ |
| 3881 + |
| 3882 +int mp_raw_size(mp_int *mp) |
| 3883 +{ |
| 3884 + ARGCHK(mp != NULL, 0); |
| 3885 + |
| 3886 + return (USED(mp) * sizeof(mp_digit)) + 1; |
| 3887 + |
| 3888 +} /* end mp_raw_size() */ |
| 3889 + |
| 3890 +/* }}} */ |
| 3891 + |
| 3892 +/* {{{ mp_toraw(mp, str) */ |
| 3893 + |
| 3894 +mp_err mp_toraw(mp_int *mp, char *str) |
| 3895 +{ |
| 3896 + int ix, jx, pos = 1; |
| 3897 + |
| 3898 + ARGCHK(mp != NULL && str != NULL, MP_BADARG); |
| 3899 + |
| 3900 + str[0] = (char)SIGN(mp); |
| 3901 + |
| 3902 + /* Iterate over each digit... */ |
| 3903 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 3904 + mp_digit d = DIGIT(mp, ix); |
| 3905 + |
| 3906 + /* Unpack digit bytes, high order first */ |
| 3907 + for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) { |
| 3908 + str[pos++] = (char)(d >> (jx * CHAR_BIT)); |
| 3909 + } |
| 3910 + } |
| 3911 + |
| 3912 + return MP_OKAY; |
| 3913 + |
| 3914 +} /* end mp_toraw() */ |
| 3915 + |
| 3916 +/* }}} */ |
| 3917 + |
| 3918 +/* {{{ mp_read_radix(mp, str, radix) */ |
| 3919 + |
| 3920 +/* |
| 3921 + mp_read_radix(mp, str, radix) |
| 3922 + |
| 3923 + Read an integer from the given string, and set mp to the resulting |
| 3924 + value. The input is presumed to be in base 10. Leading non-digit |
| 3925 + characters are ignored, and the function reads until a non-digit |
| 3926 + character or the end of the string. |
| 3927 + */ |
| 3928 + |
| 3929 +mp_err mp_read_radix(mp_int *mp, const char *str, int radix) |
| 3930 +{ |
| 3931 + int ix = 0, val = 0; |
| 3932 + mp_err res; |
| 3933 + mp_sign sig = ZPOS; |
| 3934 + |
| 3935 + ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX, |
| 3936 + MP_BADARG); |
| 3937 + |
| 3938 + mp_zero(mp); |
| 3939 + |
| 3940 + /* Skip leading non-digit characters until a digit or '-' or '+' */ |
| 3941 + while(str[ix] && |
| 3942 + (s_mp_tovalue(str[ix], radix) < 0) && |
| 3943 + str[ix] != '-' && |
| 3944 + str[ix] != '+') { |
| 3945 + ++ix; |
| 3946 + } |
| 3947 + |
| 3948 + if(str[ix] == '-') { |
| 3949 + sig = NEG; |
| 3950 + ++ix; |
| 3951 + } else if(str[ix] == '+') { |
| 3952 + sig = ZPOS; /* this is the default anyway... */ |
| 3953 + ++ix; |
| 3954 + } |
| 3955 + |
| 3956 + while((val = s_mp_tovalue(str[ix], radix)) >= 0) { |
| 3957 + if((res = s_mp_mul_d(mp, radix)) != MP_OKAY) |
| 3958 + return res; |
| 3959 + if((res = s_mp_add_d(mp, val)) != MP_OKAY) |
| 3960 + return res; |
| 3961 + ++ix; |
| 3962 + } |
| 3963 + |
| 3964 + if(s_mp_cmp_d(mp, 0) == MP_EQ) |
| 3965 + SIGN(mp) = ZPOS; |
| 3966 + else |
| 3967 + SIGN(mp) = sig; |
| 3968 + |
| 3969 + return MP_OKAY; |
| 3970 + |
| 3971 +} /* end mp_read_radix() */ |
| 3972 + |
| 3973 +mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix) |
| 3974 +{ |
| 3975 + int radix = default_radix; |
| 3976 + int cx; |
| 3977 + mp_sign sig = ZPOS; |
| 3978 + mp_err res; |
| 3979 + |
| 3980 + /* Skip leading non-digit characters until a digit or '-' or '+' */ |
| 3981 + while ((cx = *str) != 0 && |
| 3982 + (s_mp_tovalue(cx, radix) < 0) && |
| 3983 + cx != '-' && |
| 3984 + cx != '+') { |
| 3985 + ++str; |
| 3986 + } |
| 3987 + |
| 3988 + if (cx == '-') { |
| 3989 + sig = NEG; |
| 3990 + ++str; |
| 3991 + } else if (cx == '+') { |
| 3992 + sig = ZPOS; /* this is the default anyway... */ |
| 3993 + ++str; |
| 3994 + } |
| 3995 + |
| 3996 + if (str[0] == '0') { |
| 3997 + if ((str[1] | 0x20) == 'x') { |
| 3998 + radix = 16; |
| 3999 + str += 2; |
| 4000 + } else { |
| 4001 + radix = 8; |
| 4002 + str++; |
| 4003 + } |
| 4004 + } |
| 4005 + res = mp_read_radix(a, str, radix); |
| 4006 + if (res == MP_OKAY) { |
| 4007 + MP_SIGN(a) = (s_mp_cmp_d(a, 0) == MP_EQ) ? ZPOS : sig; |
| 4008 + } |
| 4009 + return res; |
| 4010 +} |
| 4011 + |
| 4012 +/* }}} */ |
| 4013 + |
| 4014 +/* {{{ mp_radix_size(mp, radix) */ |
| 4015 + |
| 4016 +int mp_radix_size(mp_int *mp, int radix) |
| 4017 +{ |
| 4018 + int bits; |
| 4019 + |
| 4020 + if(!mp || radix < 2 || radix > MAX_RADIX) |
| 4021 + return 0; |
| 4022 + |
| 4023 + bits = USED(mp) * DIGIT_BIT - 1; |
| 4024 + |
| 4025 + return s_mp_outlen(bits, radix); |
| 4026 + |
| 4027 +} /* end mp_radix_size() */ |
| 4028 + |
| 4029 +/* }}} */ |
| 4030 + |
| 4031 +/* {{{ mp_toradix(mp, str, radix) */ |
| 4032 + |
| 4033 +mp_err mp_toradix(mp_int *mp, char *str, int radix) |
| 4034 +{ |
| 4035 + int ix, pos = 0; |
| 4036 + |
| 4037 + ARGCHK(mp != NULL && str != NULL, MP_BADARG); |
| 4038 + ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE); |
| 4039 + |
| 4040 + if(mp_cmp_z(mp) == MP_EQ) { |
| 4041 + str[0] = '0'; |
| 4042 + str[1] = '\0'; |
| 4043 + } else { |
| 4044 + mp_err res; |
| 4045 + mp_int tmp; |
| 4046 + mp_sign sgn; |
| 4047 + mp_digit rem, rdx = (mp_digit)radix; |
| 4048 + char ch; |
| 4049 + |
| 4050 + if((res = mp_init_copy(&tmp, mp)) != MP_OKAY) |
| 4051 + return res; |
| 4052 + |
| 4053 + /* Save sign for later, and take absolute value */ |
| 4054 + sgn = SIGN(&tmp); SIGN(&tmp) = ZPOS; |
| 4055 + |
| 4056 + /* Generate output digits in reverse order */ |
| 4057 + while(mp_cmp_z(&tmp) != 0) { |
| 4058 + if((res = mp_div_d(&tmp, rdx, &tmp, &rem)) != MP_OKAY) { |
| 4059 + mp_clear(&tmp); |
| 4060 + return res; |
| 4061 + } |
| 4062 + |
| 4063 + /* Generate digits, use capital letters */ |
| 4064 + ch = s_mp_todigit(rem, radix, 0); |
| 4065 + |
| 4066 + str[pos++] = ch; |
| 4067 + } |
| 4068 + |
| 4069 + /* Add - sign if original value was negative */ |
| 4070 + if(sgn == NEG) |
| 4071 + str[pos++] = '-'; |
| 4072 + |
| 4073 + /* Add trailing NUL to end the string */ |
| 4074 + str[pos--] = '\0'; |
| 4075 + |
| 4076 + /* Reverse the digits and sign indicator */ |
| 4077 + ix = 0; |
| 4078 + while(ix < pos) { |
| 4079 + char tmp = str[ix]; |
| 4080 + |
| 4081 + str[ix] = str[pos]; |
| 4082 + str[pos] = tmp; |
| 4083 + ++ix; |
| 4084 + --pos; |
| 4085 + } |
| 4086 + |
| 4087 + mp_clear(&tmp); |
| 4088 + } |
| 4089 + |
| 4090 + return MP_OKAY; |
| 4091 + |
| 4092 +} /* end mp_toradix() */ |
| 4093 + |
| 4094 +/* }}} */ |
| 4095 + |
| 4096 +/* {{{ mp_tovalue(ch, r) */ |
| 4097 + |
| 4098 +int mp_tovalue(char ch, int r) |
| 4099 +{ |
| 4100 + return s_mp_tovalue(ch, r); |
| 4101 + |
| 4102 +} /* end mp_tovalue() */ |
| 4103 + |
| 4104 +/* }}} */ |
| 4105 + |
| 4106 +/* }}} */ |
| 4107 + |
| 4108 +/* {{{ mp_strerror(ec) */ |
| 4109 + |
| 4110 +/* |
| 4111 + mp_strerror(ec) |
| 4112 + |
| 4113 + Return a string describing the meaning of error code 'ec'. The |
| 4114 + string returned is allocated in static memory, so the caller should |
| 4115 + not attempt to modify or free the memory associated with this |
| 4116 + string. |
| 4117 + */ |
| 4118 +const char *mp_strerror(mp_err ec) |
| 4119 +{ |
| 4120 + int aec = (ec < 0) ? -ec : ec; |
| 4121 + |
| 4122 + /* Code values are negative, so the senses of these comparisons |
| 4123 + are accurate */ |
| 4124 + if(ec < MP_LAST_CODE || ec > MP_OKAY) { |
| 4125 + return mp_err_string[0]; /* unknown error code */ |
| 4126 + } else { |
| 4127 + return mp_err_string[aec + 1]; |
| 4128 + } |
| 4129 + |
| 4130 +} /* end mp_strerror() */ |
| 4131 + |
| 4132 +/* }}} */ |
| 4133 + |
| 4134 +/*========================================================================*/ |
| 4135 +/*------------------------------------------------------------------------*/ |
| 4136 +/* Static function definitions (internal use only) */ |
| 4137 + |
| 4138 +/* {{{ Memory management */ |
| 4139 + |
| 4140 +/* {{{ s_mp_grow(mp, min) */ |
| 4141 + |
| 4142 +/* Make sure there are at least 'min' digits allocated to mp */ |
| 4143 +mp_err s_mp_grow(mp_int *mp, mp_size min) |
| 4144 +{ |
| 4145 + if(min > ALLOC(mp)) { |
| 4146 + mp_digit *tmp; |
| 4147 + |
| 4148 + /* Set min to next nearest default precision block size */ |
| 4149 + min = MP_ROUNDUP(min, s_mp_defprec); |
| 4150 + |
| 4151 + if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL) |
| 4152 + return MP_MEM; |
| 4153 + |
| 4154 + s_mp_copy(DIGITS(mp), tmp, USED(mp)); |
| 4155 + |
| 4156 +#if MP_CRYPTO |
| 4157 + s_mp_setz(DIGITS(mp), ALLOC(mp)); |
| 4158 +#endif |
| 4159 + s_mp_free(DIGITS(mp)); |
| 4160 + DIGITS(mp) = tmp; |
| 4161 + ALLOC(mp) = min; |
| 4162 + } |
| 4163 + |
| 4164 + return MP_OKAY; |
| 4165 + |
| 4166 +} /* end s_mp_grow() */ |
| 4167 + |
| 4168 +/* }}} */ |
| 4169 + |
| 4170 +/* {{{ s_mp_pad(mp, min) */ |
| 4171 + |
| 4172 +/* Make sure the used size of mp is at least 'min', growing if needed */ |
| 4173 +mp_err s_mp_pad(mp_int *mp, mp_size min) |
| 4174 +{ |
| 4175 + if(min > USED(mp)) { |
| 4176 + mp_err res; |
| 4177 + |
| 4178 + /* Make sure there is room to increase precision */ |
| 4179 + if (min > ALLOC(mp)) { |
| 4180 + if ((res = s_mp_grow(mp, min)) != MP_OKAY) |
| 4181 + return res; |
| 4182 + } else { |
| 4183 + s_mp_setz(DIGITS(mp) + USED(mp), min - USED(mp)); |
| 4184 + } |
| 4185 + |
| 4186 + /* Increase precision; should already be 0-filled */ |
| 4187 + USED(mp) = min; |
| 4188 + } |
| 4189 + |
| 4190 + return MP_OKAY; |
| 4191 + |
| 4192 +} /* end s_mp_pad() */ |
| 4193 + |
| 4194 +/* }}} */ |
| 4195 + |
| 4196 +/* {{{ s_mp_setz(dp, count) */ |
| 4197 + |
| 4198 +#if MP_MACRO == 0 |
| 4199 +/* Set 'count' digits pointed to by dp to be zeroes */ |
| 4200 +void s_mp_setz(mp_digit *dp, mp_size count) |
| 4201 +{ |
| 4202 +#if MP_MEMSET == 0 |
| 4203 + int ix; |
| 4204 + |
| 4205 + for(ix = 0; ix < count; ix++) |
| 4206 + dp[ix] = 0; |
| 4207 +#else |
| 4208 + memset(dp, 0, count * sizeof(mp_digit)); |
| 4209 +#endif |
| 4210 + |
| 4211 +} /* end s_mp_setz() */ |
| 4212 +#endif |
| 4213 + |
| 4214 +/* }}} */ |
| 4215 + |
| 4216 +/* {{{ s_mp_copy(sp, dp, count) */ |
| 4217 + |
| 4218 +#if MP_MACRO == 0 |
| 4219 +/* Copy 'count' digits from sp to dp */ |
| 4220 +void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count) |
| 4221 +{ |
| 4222 +#if MP_MEMCPY == 0 |
| 4223 + int ix; |
| 4224 + |
| 4225 + for(ix = 0; ix < count; ix++) |
| 4226 + dp[ix] = sp[ix]; |
| 4227 +#else |
| 4228 + memcpy(dp, sp, count * sizeof(mp_digit)); |
| 4229 +#endif |
| 4230 + |
| 4231 +} /* end s_mp_copy() */ |
| 4232 +#endif |
| 4233 + |
| 4234 +/* }}} */ |
| 4235 + |
| 4236 +/* {{{ s_mp_alloc(nb, ni) */ |
| 4237 + |
| 4238 +#if MP_MACRO == 0 |
| 4239 +/* Allocate ni records of nb bytes each, and return a pointer to that */ |
| 4240 +void *s_mp_alloc(size_t nb, size_t ni) |
| 4241 +{ |
| 4242 + ++mp_allocs; |
| 4243 + return calloc(nb, ni); |
| 4244 + |
| 4245 +} /* end s_mp_alloc() */ |
| 4246 +#endif |
| 4247 + |
| 4248 +/* }}} */ |
| 4249 + |
| 4250 +/* {{{ s_mp_free(ptr) */ |
| 4251 + |
| 4252 +#if MP_MACRO == 0 |
| 4253 +/* Free the memory pointed to by ptr */ |
| 4254 +void s_mp_free(void *ptr) |
| 4255 +{ |
| 4256 + if(ptr) { |
| 4257 + ++mp_frees; |
| 4258 + free(ptr); |
| 4259 + } |
| 4260 +} /* end s_mp_free() */ |
| 4261 +#endif |
| 4262 + |
| 4263 +/* }}} */ |
| 4264 + |
| 4265 +/* {{{ s_mp_clamp(mp) */ |
| 4266 + |
| 4267 +#if MP_MACRO == 0 |
| 4268 +/* Remove leading zeroes from the given value */ |
| 4269 +void s_mp_clamp(mp_int *mp) |
| 4270 +{ |
| 4271 + mp_size used = MP_USED(mp); |
| 4272 + while (used > 1 && DIGIT(mp, used - 1) == 0) |
| 4273 + --used; |
| 4274 + MP_USED(mp) = used; |
| 4275 +} /* end s_mp_clamp() */ |
| 4276 +#endif |
| 4277 + |
| 4278 +/* }}} */ |
| 4279 + |
| 4280 +/* {{{ s_mp_exch(a, b) */ |
| 4281 + |
| 4282 +/* Exchange the data for a and b; (b, a) = (a, b) */ |
| 4283 +void s_mp_exch(mp_int *a, mp_int *b) |
| 4284 +{ |
| 4285 + mp_int tmp; |
| 4286 + |
| 4287 + tmp = *a; |
| 4288 + *a = *b; |
| 4289 + *b = tmp; |
| 4290 + |
| 4291 +} /* end s_mp_exch() */ |
| 4292 + |
| 4293 +/* }}} */ |
| 4294 + |
| 4295 +/* }}} */ |
| 4296 + |
| 4297 +/* {{{ Arithmetic helpers */ |
| 4298 + |
| 4299 +/* {{{ s_mp_lshd(mp, p) */ |
| 4300 + |
| 4301 +/* |
| 4302 + Shift mp leftward by p digits, growing if needed, and zero-filling |
| 4303 + the in-shifted digits at the right end. This is a convenient |
| 4304 + alternative to multiplication by powers of the radix |
| 4305 + The value of USED(mp) must already have been set to the value for |
| 4306 + the shifted result. |
| 4307 + */ |
| 4308 + |
| 4309 +mp_err s_mp_lshd(mp_int *mp, mp_size p) |
| 4310 +{ |
| 4311 + mp_err res; |
| 4312 + mp_size pos; |
| 4313 + int ix; |
| 4314 + |
| 4315 + if(p == 0) |
| 4316 + return MP_OKAY; |
| 4317 + |
| 4318 + if (MP_USED(mp) == 1 && MP_DIGIT(mp, 0) == 0) |
| 4319 + return MP_OKAY; |
| 4320 + |
| 4321 + if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY) |
| 4322 + return res; |
| 4323 + |
| 4324 + pos = USED(mp) - 1; |
| 4325 + |
| 4326 + /* Shift all the significant figures over as needed */ |
| 4327 + for(ix = pos - p; ix >= 0; ix--) |
| 4328 + DIGIT(mp, ix + p) = DIGIT(mp, ix); |
| 4329 + |
| 4330 + /* Fill the bottom digits with zeroes */ |
| 4331 + for(ix = 0; ix < p; ix++) |
| 4332 + DIGIT(mp, ix) = 0; |
| 4333 + |
| 4334 + return MP_OKAY; |
| 4335 + |
| 4336 +} /* end s_mp_lshd() */ |
| 4337 + |
| 4338 +/* }}} */ |
| 4339 + |
| 4340 +/* {{{ s_mp_mul_2d(mp, d) */ |
| 4341 + |
| 4342 +/* |
| 4343 + Multiply the integer by 2^d, where d is a number of bits. This |
| 4344 + amounts to a bitwise shift of the value. |
| 4345 + */ |
| 4346 +mp_err s_mp_mul_2d(mp_int *mp, mp_digit d) |
| 4347 +{ |
| 4348 + mp_err res; |
| 4349 + mp_digit dshift, bshift; |
| 4350 + mp_digit mask; |
| 4351 + |
| 4352 + ARGCHK(mp != NULL, MP_BADARG); |
| 4353 + |
| 4354 + dshift = d / MP_DIGIT_BIT; |
| 4355 + bshift = d % MP_DIGIT_BIT; |
| 4356 + /* bits to be shifted out of the top word */ |
| 4357 + mask = ((mp_digit)~0 << (MP_DIGIT_BIT - bshift)); |
| 4358 + mask &= MP_DIGIT(mp, MP_USED(mp) - 1); |
| 4359 + |
| 4360 + if (MP_OKAY != (res = s_mp_pad(mp, MP_USED(mp) + dshift + (mask != 0) ))) |
| 4361 + return res; |
| 4362 + |
| 4363 + if (dshift && MP_OKAY != (res = s_mp_lshd(mp, dshift))) |
| 4364 + return res; |
| 4365 + |
| 4366 + if (bshift) { |
| 4367 + mp_digit *pa = MP_DIGITS(mp); |
| 4368 + mp_digit *alim = pa + MP_USED(mp); |
| 4369 + mp_digit prev = 0; |
| 4370 + |
| 4371 + for (pa += dshift; pa < alim; ) { |
| 4372 + mp_digit x = *pa; |
| 4373 + *pa++ = (x << bshift) | prev; |
| 4374 + prev = x >> (DIGIT_BIT - bshift); |
| 4375 + } |
| 4376 + } |
| 4377 + |
| 4378 + s_mp_clamp(mp); |
| 4379 + return MP_OKAY; |
| 4380 +} /* end s_mp_mul_2d() */ |
| 4381 + |
| 4382 +/* {{{ s_mp_rshd(mp, p) */ |
| 4383 + |
| 4384 +/* |
| 4385 + Shift mp rightward by p digits. Maintains the invariant that |
| 4386 + digits above the precision are all zero. Digits shifted off the |
| 4387 + end are lost. Cannot fail. |
| 4388 + */ |
| 4389 + |
| 4390 +void s_mp_rshd(mp_int *mp, mp_size p) |
| 4391 +{ |
| 4392 + mp_size ix; |
| 4393 + mp_digit *src, *dst; |
| 4394 + |
| 4395 + if(p == 0) |
| 4396 + return; |
| 4397 + |
| 4398 + /* Shortcut when all digits are to be shifted off */ |
| 4399 + if(p >= USED(mp)) { |
| 4400 + s_mp_setz(DIGITS(mp), ALLOC(mp)); |
| 4401 + USED(mp) = 1; |
| 4402 + SIGN(mp) = ZPOS; |
| 4403 + return; |
| 4404 + } |
| 4405 + |
| 4406 + /* Shift all the significant figures over as needed */ |
| 4407 + dst = MP_DIGITS(mp); |
| 4408 + src = dst + p; |
| 4409 + for (ix = USED(mp) - p; ix > 0; ix--) |
| 4410 + *dst++ = *src++; |
| 4411 + |
| 4412 + MP_USED(mp) -= p; |
| 4413 + /* Fill the top digits with zeroes */ |
| 4414 + while (p-- > 0) |
| 4415 + *dst++ = 0; |
| 4416 + |
| 4417 +#if 0 |
| 4418 + /* Strip off any leading zeroes */ |
| 4419 + s_mp_clamp(mp); |
| 4420 +#endif |
| 4421 + |
| 4422 +} /* end s_mp_rshd() */ |
| 4423 + |
| 4424 +/* }}} */ |
| 4425 + |
| 4426 +/* {{{ s_mp_div_2(mp) */ |
| 4427 + |
| 4428 +/* Divide by two -- take advantage of radix properties to do it fast */ |
| 4429 +void s_mp_div_2(mp_int *mp) |
| 4430 +{ |
| 4431 + s_mp_div_2d(mp, 1); |
| 4432 + |
| 4433 +} /* end s_mp_div_2() */ |
| 4434 + |
| 4435 +/* }}} */ |
| 4436 + |
| 4437 +/* {{{ s_mp_mul_2(mp) */ |
| 4438 + |
| 4439 +mp_err s_mp_mul_2(mp_int *mp) |
| 4440 +{ |
| 4441 + mp_digit *pd; |
| 4442 + int ix, used; |
| 4443 + mp_digit kin = 0; |
| 4444 + |
| 4445 + /* Shift digits leftward by 1 bit */ |
| 4446 + used = MP_USED(mp); |
| 4447 + pd = MP_DIGITS(mp); |
| 4448 + for (ix = 0; ix < used; ix++) { |
| 4449 + mp_digit d = *pd; |
| 4450 + *pd++ = (d << 1) | kin; |
| 4451 + kin = (d >> (DIGIT_BIT - 1)); |
| 4452 + } |
| 4453 + |
| 4454 + /* Deal with rollover from last digit */ |
| 4455 + if (kin) { |
| 4456 + if (ix >= ALLOC(mp)) { |
| 4457 + mp_err res; |
| 4458 + if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY) |
| 4459 + return res; |
| 4460 + } |
| 4461 + |
| 4462 + DIGIT(mp, ix) = kin; |
| 4463 + USED(mp) += 1; |
| 4464 + } |
| 4465 + |
| 4466 + return MP_OKAY; |
| 4467 + |
| 4468 +} /* end s_mp_mul_2() */ |
| 4469 + |
| 4470 +/* }}} */ |
| 4471 + |
| 4472 +/* {{{ s_mp_mod_2d(mp, d) */ |
| 4473 + |
| 4474 +/* |
| 4475 + Remainder the integer by 2^d, where d is a number of bits. This |
| 4476 + amounts to a bitwise AND of the value, and does not require the full |
| 4477 + division code |
| 4478 + */ |
| 4479 +void s_mp_mod_2d(mp_int *mp, mp_digit d) |
| 4480 +{ |
| 4481 + mp_size ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT); |
| 4482 + mp_size ix; |
| 4483 + mp_digit dmask; |
| 4484 + |
| 4485 + if(ndig >= USED(mp)) |
| 4486 + return; |
| 4487 + |
| 4488 + /* Flush all the bits above 2^d in its digit */ |
| 4489 + dmask = ((mp_digit)1 << nbit) - 1; |
| 4490 + DIGIT(mp, ndig) &= dmask; |
| 4491 + |
| 4492 + /* Flush all digits above the one with 2^d in it */ |
| 4493 + for(ix = ndig + 1; ix < USED(mp); ix++) |
| 4494 + DIGIT(mp, ix) = 0; |
| 4495 + |
| 4496 + s_mp_clamp(mp); |
| 4497 + |
| 4498 +} /* end s_mp_mod_2d() */ |
| 4499 + |
| 4500 +/* }}} */ |
| 4501 + |
| 4502 +/* {{{ s_mp_div_2d(mp, d) */ |
| 4503 + |
| 4504 +/* |
| 4505 + Divide the integer by 2^d, where d is a number of bits. This |
| 4506 + amounts to a bitwise shift of the value, and does not require the |
| 4507 + full division code (used in Barrett reduction, see below) |
| 4508 + */ |
| 4509 +void s_mp_div_2d(mp_int *mp, mp_digit d) |
| 4510 +{ |
| 4511 + int ix; |
| 4512 + mp_digit save, next, mask; |
| 4513 + |
| 4514 + s_mp_rshd(mp, d / DIGIT_BIT); |
| 4515 + d %= DIGIT_BIT; |
| 4516 + if (d) { |
| 4517 + mask = ((mp_digit)1 << d) - 1; |
| 4518 + save = 0; |
| 4519 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 4520 + next = DIGIT(mp, ix) & mask; |
| 4521 + DIGIT(mp, ix) = (DIGIT(mp, ix) >> d) | (save << (DIGIT_BIT - d)); |
| 4522 + save = next; |
| 4523 + } |
| 4524 + } |
| 4525 + s_mp_clamp(mp); |
| 4526 + |
| 4527 +} /* end s_mp_div_2d() */ |
| 4528 + |
| 4529 +/* }}} */ |
| 4530 + |
| 4531 +/* {{{ s_mp_norm(a, b, *d) */ |
| 4532 + |
| 4533 +/* |
| 4534 + s_mp_norm(a, b, *d) |
| 4535 + |
| 4536 + Normalize a and b for division, where b is the divisor. In order |
| 4537 + that we might make good guesses for quotient digits, we want the |
| 4538 + leading digit of b to be at least half the radix, which we |
| 4539 + accomplish by multiplying a and b by a power of 2. The exponent |
| 4540 + (shift count) is placed in *pd, so that the remainder can be shifted |
| 4541 + back at the end of the division process. |
| 4542 + */ |
| 4543 + |
| 4544 +mp_err s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd) |
| 4545 +{ |
| 4546 + mp_digit d; |
| 4547 + mp_digit mask; |
| 4548 + mp_digit b_msd; |
| 4549 + mp_err res = MP_OKAY; |
| 4550 + |
| 4551 + d = 0; |
| 4552 + mask = DIGIT_MAX & ~(DIGIT_MAX >> 1); /* mask is msb of digit */ |
| 4553 + b_msd = DIGIT(b, USED(b) - 1); |
| 4554 + while (!(b_msd & mask)) { |
| 4555 + b_msd <<= 1; |
| 4556 + ++d; |
| 4557 + } |
| 4558 + |
| 4559 + if (d) { |
| 4560 + MP_CHECKOK( s_mp_mul_2d(a, d) ); |
| 4561 + MP_CHECKOK( s_mp_mul_2d(b, d) ); |
| 4562 + } |
| 4563 + |
| 4564 + *pd = d; |
| 4565 +CLEANUP: |
| 4566 + return res; |
| 4567 + |
| 4568 +} /* end s_mp_norm() */ |
| 4569 + |
| 4570 +/* }}} */ |
| 4571 + |
| 4572 +/* }}} */ |
| 4573 + |
| 4574 +/* {{{ Primitive digit arithmetic */ |
| 4575 + |
| 4576 +/* {{{ s_mp_add_d(mp, d) */ |
| 4577 + |
| 4578 +/* Add d to |mp| in place */ |
| 4579 +mp_err s_mp_add_d(mp_int *mp, mp_digit d) /* unsigned digit addition */ |
| 4580 +{ |
| 4581 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4582 + mp_word w, k = 0; |
| 4583 + mp_size ix = 1; |
| 4584 + |
| 4585 + w = (mp_word)DIGIT(mp, 0) + d; |
| 4586 + DIGIT(mp, 0) = ACCUM(w); |
| 4587 + k = CARRYOUT(w); |
| 4588 + |
| 4589 + while(ix < USED(mp) && k) { |
| 4590 + w = (mp_word)DIGIT(mp, ix) + k; |
| 4591 + DIGIT(mp, ix) = ACCUM(w); |
| 4592 + k = CARRYOUT(w); |
| 4593 + ++ix; |
| 4594 + } |
| 4595 + |
| 4596 + if(k != 0) { |
| 4597 + mp_err res; |
| 4598 + |
| 4599 + if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY) |
| 4600 + return res; |
| 4601 + |
| 4602 + DIGIT(mp, ix) = (mp_digit)k; |
| 4603 + } |
| 4604 + |
| 4605 + return MP_OKAY; |
| 4606 +#else |
| 4607 + mp_digit * pmp = MP_DIGITS(mp); |
| 4608 + mp_digit sum, mp_i, carry = 0; |
| 4609 + mp_err res = MP_OKAY; |
| 4610 + int used = (int)MP_USED(mp); |
| 4611 + |
| 4612 + mp_i = *pmp; |
| 4613 + *pmp++ = sum = d + mp_i; |
| 4614 + carry = (sum < d); |
| 4615 + while (carry && --used > 0) { |
| 4616 + mp_i = *pmp; |
| 4617 + *pmp++ = sum = carry + mp_i; |
| 4618 + carry = !sum; |
| 4619 + } |
| 4620 + if (carry && !used) { |
| 4621 + /* mp is growing */ |
| 4622 + used = MP_USED(mp); |
| 4623 + MP_CHECKOK( s_mp_pad(mp, used + 1) ); |
| 4624 + MP_DIGIT(mp, used) = carry; |
| 4625 + } |
| 4626 +CLEANUP: |
| 4627 + return res; |
| 4628 +#endif |
| 4629 +} /* end s_mp_add_d() */ |
| 4630 + |
| 4631 +/* }}} */ |
| 4632 + |
| 4633 +/* {{{ s_mp_sub_d(mp, d) */ |
| 4634 + |
| 4635 +/* Subtract d from |mp| in place, assumes |mp| > d */ |
| 4636 +mp_err s_mp_sub_d(mp_int *mp, mp_digit d) /* unsigned digit subtract */ |
| 4637 +{ |
| 4638 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 4639 + mp_word w, b = 0; |
| 4640 + mp_size ix = 1; |
| 4641 + |
| 4642 + /* Compute initial subtraction */ |
| 4643 + w = (RADIX + (mp_word)DIGIT(mp, 0)) - d; |
| 4644 + b = CARRYOUT(w) ? 0 : 1; |
| 4645 + DIGIT(mp, 0) = ACCUM(w); |
| 4646 + |
| 4647 + /* Propagate borrows leftward */ |
| 4648 + while(b && ix < USED(mp)) { |
| 4649 + w = (RADIX + (mp_word)DIGIT(mp, ix)) - b; |
| 4650 + b = CARRYOUT(w) ? 0 : 1; |
| 4651 + DIGIT(mp, ix) = ACCUM(w); |
| 4652 + ++ix; |
| 4653 + } |
| 4654 + |
| 4655 + /* Remove leading zeroes */ |
| 4656 + s_mp_clamp(mp); |
| 4657 + |
| 4658 + /* If we have a borrow out, it's a violation of the input invariant */ |
| 4659 + if(b) |
| 4660 + return MP_RANGE; |
| 4661 + else |
| 4662 + return MP_OKAY; |
| 4663 +#else |
| 4664 + mp_digit *pmp = MP_DIGITS(mp); |
| 4665 + mp_digit mp_i, diff, borrow; |
| 4666 + mp_size used = MP_USED(mp); |
| 4667 + |
| 4668 + mp_i = *pmp; |
| 4669 + *pmp++ = diff = mp_i - d; |
| 4670 + borrow = (diff > mp_i); |
| 4671 + while (borrow && --used) { |
| 4672 + mp_i = *pmp; |
| 4673 + *pmp++ = diff = mp_i - borrow; |
| 4674 + borrow = (diff > mp_i); |
| 4675 + } |
| 4676 + s_mp_clamp(mp); |
| 4677 + return (borrow && !used) ? MP_RANGE : MP_OKAY; |
| 4678 +#endif |
| 4679 +} /* end s_mp_sub_d() */ |
| 4680 + |
| 4681 +/* }}} */ |
| 4682 + |
| 4683 +/* {{{ s_mp_mul_d(a, d) */ |
| 4684 + |
| 4685 +/* Compute a = a * d, single digit multiplication */ |
| 4686 +mp_err s_mp_mul_d(mp_int *a, mp_digit d) |
| 4687 +{ |
| 4688 + mp_err res; |
| 4689 + mp_size used; |
| 4690 + int pow; |
| 4691 + |
| 4692 + if (!d) { |
| 4693 + mp_zero(a); |
| 4694 + return MP_OKAY; |
| 4695 + } |
| 4696 + if (d == 1) |
| 4697 + return MP_OKAY; |
| 4698 + if (0 <= (pow = s_mp_ispow2d(d))) { |
| 4699 + return s_mp_mul_2d(a, (mp_digit)pow); |
| 4700 + } |
| 4701 + |
| 4702 + used = MP_USED(a); |
| 4703 + MP_CHECKOK( s_mp_pad(a, used + 1) ); |
| 4704 + |
| 4705 + s_mpv_mul_d(MP_DIGITS(a), used, d, MP_DIGITS(a)); |
| 4706 + |
| 4707 + s_mp_clamp(a); |
| 4708 + |
| 4709 +CLEANUP: |
| 4710 + return res; |
| 4711 + |
| 4712 +} /* end s_mp_mul_d() */ |
| 4713 + |
| 4714 +/* }}} */ |
| 4715 + |
| 4716 +/* {{{ s_mp_div_d(mp, d, r) */ |
| 4717 + |
| 4718 +/* |
| 4719 + s_mp_div_d(mp, d, r) |
| 4720 + |
| 4721 + Compute the quotient mp = mp / d and remainder r = mp mod d, for a |
| 4722 + single digit d. If r is null, the remainder will be discarded. |
| 4723 + */ |
| 4724 + |
| 4725 +mp_err s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r) |
| 4726 +{ |
| 4727 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD) |
| 4728 + mp_word w = 0, q; |
| 4729 +#else |
| 4730 + mp_digit w, q; |
| 4731 +#endif |
| 4732 + int ix; |
| 4733 + mp_err res; |
| 4734 + mp_int quot; |
| 4735 + mp_int rem; |
| 4736 + |
| 4737 + if(d == 0) |
| 4738 + return MP_RANGE; |
| 4739 + if (d == 1) { |
| 4740 + if (r) |
| 4741 + *r = 0; |
| 4742 + return MP_OKAY; |
| 4743 + } |
| 4744 + /* could check for power of 2 here, but mp_div_d does that. */ |
| 4745 + if (MP_USED(mp) == 1) { |
| 4746 + mp_digit n = MP_DIGIT(mp,0); |
| 4747 + mp_digit rem; |
| 4748 + |
| 4749 + q = n / d; |
| 4750 + rem = n % d; |
| 4751 + MP_DIGIT(mp,0) = q; |
| 4752 + if (r) |
| 4753 + *r = rem; |
| 4754 + return MP_OKAY; |
| 4755 + } |
| 4756 + |
| 4757 + MP_DIGITS(&rem) = 0; |
| 4758 + MP_DIGITS(") = 0; |
| 4759 + /* Make room for the quotient */ |
| 4760 + MP_CHECKOK( mp_init_size(", USED(mp)) ); |
| 4761 + |
| 4762 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD) |
| 4763 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 4764 + w = (w << DIGIT_BIT) | DIGIT(mp, ix); |
| 4765 + |
| 4766 + if(w >= d) { |
| 4767 + q = w / d; |
| 4768 + w = w % d; |
| 4769 + } else { |
| 4770 + q = 0; |
| 4771 + } |
| 4772 + |
| 4773 + s_mp_lshd(", 1); |
| 4774 + DIGIT(", 0) = (mp_digit)q; |
| 4775 + } |
| 4776 +#else |
| 4777 + { |
| 4778 + mp_digit p; |
| 4779 +#if !defined(MP_ASSEMBLY_DIV_2DX1D) |
| 4780 + mp_digit norm; |
| 4781 +#endif |
| 4782 + |
| 4783 + MP_CHECKOK( mp_init_copy(&rem, mp) ); |
| 4784 + |
| 4785 +#if !defined(MP_ASSEMBLY_DIV_2DX1D) |
| 4786 + MP_DIGIT(", 0) = d; |
| 4787 + MP_CHECKOK( s_mp_norm(&rem, ", &norm) ); |
| 4788 + if (norm) |
| 4789 + d <<= norm; |
| 4790 + MP_DIGIT(", 0) = 0; |
| 4791 +#endif |
| 4792 + |
| 4793 + p = 0; |
| 4794 + for (ix = USED(&rem) - 1; ix >= 0; ix--) { |
| 4795 + w = DIGIT(&rem, ix); |
| 4796 + |
| 4797 + if (p) { |
| 4798 + MP_CHECKOK( s_mpv_div_2dx1d(p, w, d, &q, &w) ); |
| 4799 + } else if (w >= d) { |
| 4800 + q = w / d; |
| 4801 + w = w % d; |
| 4802 + } else { |
| 4803 + q = 0; |
| 4804 + } |
| 4805 + |
| 4806 + MP_CHECKOK( s_mp_lshd(", 1) ); |
| 4807 + DIGIT(", 0) = q; |
| 4808 + p = w; |
| 4809 + } |
| 4810 +#if !defined(MP_ASSEMBLY_DIV_2DX1D) |
| 4811 + if (norm) |
| 4812 + w >>= norm; |
| 4813 +#endif |
| 4814 + } |
| 4815 +#endif |
| 4816 + |
| 4817 + /* Deliver the remainder, if desired */ |
| 4818 + if(r) |
| 4819 + *r = (mp_digit)w; |
| 4820 + |
| 4821 + s_mp_clamp("); |
| 4822 + mp_exch(", mp); |
| 4823 +CLEANUP: |
| 4824 + mp_clear("); |
| 4825 + mp_clear(&rem); |
| 4826 + |
| 4827 + return res; |
| 4828 +} /* end s_mp_div_d() */ |
| 4829 + |
| 4830 +/* }}} */ |
| 4831 + |
| 4832 + |
| 4833 +/* }}} */ |
| 4834 + |
| 4835 +/* {{{ Primitive full arithmetic */ |
| 4836 + |
| 4837 +/* {{{ s_mp_add(a, b) */ |
| 4838 + |
| 4839 +/* Compute a = |a| + |b| */ |
| 4840 +mp_err s_mp_add(mp_int *a, const mp_int *b) /* magnitude addition */ |
| 4841 +{ |
| 4842 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4843 + mp_word w = 0; |
| 4844 +#else |
| 4845 + mp_digit d, sum, carry = 0; |
| 4846 +#endif |
| 4847 + mp_digit *pa, *pb; |
| 4848 + mp_size ix; |
| 4849 + mp_size used; |
| 4850 + mp_err res; |
| 4851 + |
| 4852 + /* Make sure a has enough precision for the output value */ |
| 4853 + if((USED(b) > USED(a)) && (res = s_mp_pad(a, USED(b))) != MP_OKAY) |
| 4854 + return res; |
| 4855 + |
| 4856 + /* |
| 4857 + Add up all digits up to the precision of b. If b had initially |
| 4858 + the same precision as a, or greater, we took care of it by the |
| 4859 + padding step above, so there is no problem. If b had initially |
| 4860 + less precision, we'll have to make sure the carry out is duly |
| 4861 + propagated upward among the higher-order digits of the sum. |
| 4862 + */ |
| 4863 + pa = MP_DIGITS(a); |
| 4864 + pb = MP_DIGITS(b); |
| 4865 + used = MP_USED(b); |
| 4866 + for(ix = 0; ix < used; ix++) { |
| 4867 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4868 + w = w + *pa + *pb++; |
| 4869 + *pa++ = ACCUM(w); |
| 4870 + w = CARRYOUT(w); |
| 4871 +#else |
| 4872 + d = *pa; |
| 4873 + sum = d + *pb++; |
| 4874 + d = (sum < d); /* detect overflow */ |
| 4875 + *pa++ = sum += carry; |
| 4876 + carry = d + (sum < carry); /* detect overflow */ |
| 4877 +#endif |
| 4878 + } |
| 4879 + |
| 4880 + /* If we run out of 'b' digits before we're actually done, make |
| 4881 + sure the carries get propagated upward... |
| 4882 + */ |
| 4883 + used = MP_USED(a); |
| 4884 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4885 + while (w && ix < used) { |
| 4886 + w = w + *pa; |
| 4887 + *pa++ = ACCUM(w); |
| 4888 + w = CARRYOUT(w); |
| 4889 + ++ix; |
| 4890 + } |
| 4891 +#else |
| 4892 + while (carry && ix < used) { |
| 4893 + sum = carry + *pa; |
| 4894 + *pa++ = sum; |
| 4895 + carry = !sum; |
| 4896 + ++ix; |
| 4897 + } |
| 4898 +#endif |
| 4899 + |
| 4900 + /* If there's an overall carry out, increase precision and include |
| 4901 + it. We could have done this initially, but why touch the memory |
| 4902 + allocator unless we're sure we have to? |
| 4903 + */ |
| 4904 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4905 + if (w) { |
| 4906 + if((res = s_mp_pad(a, used + 1)) != MP_OKAY) |
| 4907 + return res; |
| 4908 + |
| 4909 + DIGIT(a, ix) = (mp_digit)w; |
| 4910 + } |
| 4911 +#else |
| 4912 + if (carry) { |
| 4913 + if((res = s_mp_pad(a, used + 1)) != MP_OKAY) |
| 4914 + return res; |
| 4915 + |
| 4916 + DIGIT(a, used) = carry; |
| 4917 + } |
| 4918 +#endif |
| 4919 + |
| 4920 + return MP_OKAY; |
| 4921 +} /* end s_mp_add() */ |
| 4922 + |
| 4923 +/* }}} */ |
| 4924 + |
| 4925 +/* Compute c = |a| + |b| */ /* magnitude addition */ |
| 4926 +mp_err s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c) |
| 4927 +{ |
| 4928 + mp_digit *pa, *pb, *pc; |
| 4929 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4930 + mp_word w = 0; |
| 4931 +#else |
| 4932 + mp_digit sum, carry = 0, d; |
| 4933 +#endif |
| 4934 + mp_size ix; |
| 4935 + mp_size used; |
| 4936 + mp_err res; |
| 4937 + |
| 4938 + MP_SIGN(c) = MP_SIGN(a); |
| 4939 + if (MP_USED(a) < MP_USED(b)) { |
| 4940 + const mp_int *xch = a; |
| 4941 + a = b; |
| 4942 + b = xch; |
| 4943 + } |
| 4944 + |
| 4945 + /* Make sure a has enough precision for the output value */ |
| 4946 + if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a)))) |
| 4947 + return res; |
| 4948 + |
| 4949 + /* |
| 4950 + Add up all digits up to the precision of b. If b had initially |
| 4951 + the same precision as a, or greater, we took care of it by the |
| 4952 + exchange step above, so there is no problem. If b had initially |
| 4953 + less precision, we'll have to make sure the carry out is duly |
| 4954 + propagated upward among the higher-order digits of the sum. |
| 4955 + */ |
| 4956 + pa = MP_DIGITS(a); |
| 4957 + pb = MP_DIGITS(b); |
| 4958 + pc = MP_DIGITS(c); |
| 4959 + used = MP_USED(b); |
| 4960 + for (ix = 0; ix < used; ix++) { |
| 4961 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4962 + w = w + *pa++ + *pb++; |
| 4963 + *pc++ = ACCUM(w); |
| 4964 + w = CARRYOUT(w); |
| 4965 +#else |
| 4966 + d = *pa++; |
| 4967 + sum = d + *pb++; |
| 4968 + d = (sum < d); /* detect overflow */ |
| 4969 + *pc++ = sum += carry; |
| 4970 + carry = d + (sum < carry); /* detect overflow */ |
| 4971 +#endif |
| 4972 + } |
| 4973 + |
| 4974 + /* If we run out of 'b' digits before we're actually done, make |
| 4975 + sure the carries get propagated upward... |
| 4976 + */ |
| 4977 + for (used = MP_USED(a); ix < used; ++ix) { |
| 4978 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4979 + w = w + *pa++; |
| 4980 + *pc++ = ACCUM(w); |
| 4981 + w = CARRYOUT(w); |
| 4982 +#else |
| 4983 + *pc++ = sum = carry + *pa++; |
| 4984 + carry = (sum < carry); |
| 4985 +#endif |
| 4986 + } |
| 4987 + |
| 4988 + /* If there's an overall carry out, increase precision and include |
| 4989 + it. We could have done this initially, but why touch the memory |
| 4990 + allocator unless we're sure we have to? |
| 4991 + */ |
| 4992 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 4993 + if (w) { |
| 4994 + if((res = s_mp_pad(c, used + 1)) != MP_OKAY) |
| 4995 + return res; |
| 4996 + |
| 4997 + DIGIT(c, used) = (mp_digit)w; |
| 4998 + ++used; |
| 4999 + } |
| 5000 +#else |
| 5001 + if (carry) { |
| 5002 + if((res = s_mp_pad(c, used + 1)) != MP_OKAY) |
| 5003 + return res; |
| 5004 + |
| 5005 + DIGIT(c, used) = carry; |
| 5006 + ++used; |
| 5007 + } |
| 5008 +#endif |
| 5009 + MP_USED(c) = used; |
| 5010 + return MP_OKAY; |
| 5011 +} |
| 5012 +/* {{{ s_mp_add_offset(a, b, offset) */ |
| 5013 + |
| 5014 +/* Compute a = |a| + ( |b| * (RADIX ** offset) ) */ |
| 5015 +mp_err s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset) |
| 5016 +{ |
| 5017 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 5018 + mp_word w, k = 0; |
| 5019 +#else |
| 5020 + mp_digit d, sum, carry = 0; |
| 5021 +#endif |
| 5022 + mp_size ib; |
| 5023 + mp_size ia; |
| 5024 + mp_size lim; |
| 5025 + mp_err res; |
| 5026 + |
| 5027 + /* Make sure a has enough precision for the output value */ |
| 5028 + lim = MP_USED(b) + offset; |
| 5029 + if((lim > USED(a)) && (res = s_mp_pad(a, lim)) != MP_OKAY) |
| 5030 + return res; |
| 5031 + |
| 5032 + /* |
| 5033 + Add up all digits up to the precision of b. If b had initially |
| 5034 + the same precision as a, or greater, we took care of it by the |
| 5035 + padding step above, so there is no problem. If b had initially |
| 5036 + less precision, we'll have to make sure the carry out is duly |
| 5037 + propagated upward among the higher-order digits of the sum. |
| 5038 + */ |
| 5039 + lim = USED(b); |
| 5040 + for(ib = 0, ia = offset; ib < lim; ib++, ia++) { |
| 5041 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 5042 + w = (mp_word)DIGIT(a, ia) + DIGIT(b, ib) + k; |
| 5043 + DIGIT(a, ia) = ACCUM(w); |
| 5044 + k = CARRYOUT(w); |
| 5045 +#else |
| 5046 + d = MP_DIGIT(a, ia); |
| 5047 + sum = d + MP_DIGIT(b, ib); |
| 5048 + d = (sum < d); |
| 5049 + MP_DIGIT(a,ia) = sum += carry; |
| 5050 + carry = d + (sum < carry); |
| 5051 +#endif |
| 5052 + } |
| 5053 + |
| 5054 + /* If we run out of 'b' digits before we're actually done, make |
| 5055 + sure the carries get propagated upward... |
| 5056 + */ |
| 5057 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 5058 + for (lim = MP_USED(a); k && (ia < lim); ++ia) { |
| 5059 + w = (mp_word)DIGIT(a, ia) + k; |
| 5060 + DIGIT(a, ia) = ACCUM(w); |
| 5061 + k = CARRYOUT(w); |
| 5062 + } |
| 5063 +#else |
| 5064 + for (lim = MP_USED(a); carry && (ia < lim); ++ia) { |
| 5065 + d = MP_DIGIT(a, ia); |
| 5066 + MP_DIGIT(a,ia) = sum = d + carry; |
| 5067 + carry = (sum < d); |
| 5068 + } |
| 5069 +#endif |
| 5070 + |
| 5071 + /* If there's an overall carry out, increase precision and include |
| 5072 + it. We could have done this initially, but why touch the memory |
| 5073 + allocator unless we're sure we have to? |
| 5074 + */ |
| 5075 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) |
| 5076 + if(k) { |
| 5077 + if((res = s_mp_pad(a, USED(a) + 1)) != MP_OKAY) |
| 5078 + return res; |
| 5079 + |
| 5080 + DIGIT(a, ia) = (mp_digit)k; |
| 5081 + } |
| 5082 +#else |
| 5083 + if (carry) { |
| 5084 + if((res = s_mp_pad(a, lim + 1)) != MP_OKAY) |
| 5085 + return res; |
| 5086 + |
| 5087 + DIGIT(a, lim) = carry; |
| 5088 + } |
| 5089 +#endif |
| 5090 + s_mp_clamp(a); |
| 5091 + |
| 5092 + return MP_OKAY; |
| 5093 + |
| 5094 +} /* end s_mp_add_offset() */ |
| 5095 + |
| 5096 +/* }}} */ |
| 5097 + |
| 5098 +/* {{{ s_mp_sub(a, b) */ |
| 5099 + |
| 5100 +/* Compute a = |a| - |b|, assumes |a| >= |b| */ |
| 5101 +mp_err s_mp_sub(mp_int *a, const mp_int *b) /* magnitude subtract */ |
| 5102 +{ |
| 5103 + mp_digit *pa, *pb, *limit; |
| 5104 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5105 + mp_sword w = 0; |
| 5106 +#else |
| 5107 + mp_digit d, diff, borrow = 0; |
| 5108 +#endif |
| 5109 + |
| 5110 + /* |
| 5111 + Subtract and propagate borrow. Up to the precision of b, this |
| 5112 + accounts for the digits of b; after that, we just make sure the |
| 5113 + carries get to the right place. This saves having to pad b out to |
| 5114 + the precision of a just to make the loops work right... |
| 5115 + */ |
| 5116 + pa = MP_DIGITS(a); |
| 5117 + pb = MP_DIGITS(b); |
| 5118 + limit = pb + MP_USED(b); |
| 5119 + while (pb < limit) { |
| 5120 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5121 + w = w + *pa - *pb++; |
| 5122 + *pa++ = ACCUM(w); |
| 5123 + w >>= MP_DIGIT_BIT; |
| 5124 +#else |
| 5125 + d = *pa; |
| 5126 + diff = d - *pb++; |
| 5127 + d = (diff > d); /* detect borrow */ |
| 5128 + if (borrow && --diff == MP_DIGIT_MAX) |
| 5129 + ++d; |
| 5130 + *pa++ = diff; |
| 5131 + borrow = d; |
| 5132 +#endif |
| 5133 + } |
| 5134 + limit = MP_DIGITS(a) + MP_USED(a); |
| 5135 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5136 + while (w && pa < limit) { |
| 5137 + w = w + *pa; |
| 5138 + *pa++ = ACCUM(w); |
| 5139 + w >>= MP_DIGIT_BIT; |
| 5140 + } |
| 5141 +#else |
| 5142 + while (borrow && pa < limit) { |
| 5143 + d = *pa; |
| 5144 + *pa++ = diff = d - borrow; |
| 5145 + borrow = (diff > d); |
| 5146 + } |
| 5147 +#endif |
| 5148 + |
| 5149 + /* Clobber any leading zeroes we created */ |
| 5150 + s_mp_clamp(a); |
| 5151 + |
| 5152 + /* |
| 5153 + If there was a borrow out, then |b| > |a| in violation |
| 5154 + of our input invariant. We've already done the work, |
| 5155 + but we'll at least complain about it... |
| 5156 + */ |
| 5157 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5158 + return w ? MP_RANGE : MP_OKAY; |
| 5159 +#else |
| 5160 + return borrow ? MP_RANGE : MP_OKAY; |
| 5161 +#endif |
| 5162 +} /* end s_mp_sub() */ |
| 5163 + |
| 5164 +/* }}} */ |
| 5165 + |
| 5166 +/* Compute c = |a| - |b|, assumes |a| >= |b| */ /* magnitude subtract */ |
| 5167 +mp_err s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c) |
| 5168 +{ |
| 5169 + mp_digit *pa, *pb, *pc; |
| 5170 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5171 + mp_sword w = 0; |
| 5172 +#else |
| 5173 + mp_digit d, diff, borrow = 0; |
| 5174 +#endif |
| 5175 + int ix, limit; |
| 5176 + mp_err res; |
| 5177 + |
| 5178 + MP_SIGN(c) = MP_SIGN(a); |
| 5179 + |
| 5180 + /* Make sure a has enough precision for the output value */ |
| 5181 + if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a)))) |
| 5182 + return res; |
| 5183 + |
| 5184 + /* |
| 5185 + Subtract and propagate borrow. Up to the precision of b, this |
| 5186 + accounts for the digits of b; after that, we just make sure the |
| 5187 + carries get to the right place. This saves having to pad b out to |
| 5188 + the precision of a just to make the loops work right... |
| 5189 + */ |
| 5190 + pa = MP_DIGITS(a); |
| 5191 + pb = MP_DIGITS(b); |
| 5192 + pc = MP_DIGITS(c); |
| 5193 + limit = MP_USED(b); |
| 5194 + for (ix = 0; ix < limit; ++ix) { |
| 5195 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5196 + w = w + *pa++ - *pb++; |
| 5197 + *pc++ = ACCUM(w); |
| 5198 + w >>= MP_DIGIT_BIT; |
| 5199 +#else |
| 5200 + d = *pa++; |
| 5201 + diff = d - *pb++; |
| 5202 + d = (diff > d); |
| 5203 + if (borrow && --diff == MP_DIGIT_MAX) |
| 5204 + ++d; |
| 5205 + *pc++ = diff; |
| 5206 + borrow = d; |
| 5207 +#endif |
| 5208 + } |
| 5209 + for (limit = MP_USED(a); ix < limit; ++ix) { |
| 5210 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5211 + w = w + *pa++; |
| 5212 + *pc++ = ACCUM(w); |
| 5213 + w >>= MP_DIGIT_BIT; |
| 5214 +#else |
| 5215 + d = *pa++; |
| 5216 + *pc++ = diff = d - borrow; |
| 5217 + borrow = (diff > d); |
| 5218 +#endif |
| 5219 + } |
| 5220 + |
| 5221 + /* Clobber any leading zeroes we created */ |
| 5222 + MP_USED(c) = ix; |
| 5223 + s_mp_clamp(c); |
| 5224 + |
| 5225 + /* |
| 5226 + If there was a borrow out, then |b| > |a| in violation |
| 5227 + of our input invariant. We've already done the work, |
| 5228 + but we'll at least complain about it... |
| 5229 + */ |
| 5230 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD) |
| 5231 + return w ? MP_RANGE : MP_OKAY; |
| 5232 +#else |
| 5233 + return borrow ? MP_RANGE : MP_OKAY; |
| 5234 +#endif |
| 5235 +} |
| 5236 +/* {{{ s_mp_mul(a, b) */ |
| 5237 + |
| 5238 +/* Compute a = |a| * |b| */ |
| 5239 +mp_err s_mp_mul(mp_int *a, const mp_int *b) |
| 5240 +{ |
| 5241 + return mp_mul(a, b, a); |
| 5242 +} /* end s_mp_mul() */ |
| 5243 + |
| 5244 +/* }}} */ |
| 5245 + |
| 5246 +#if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY) |
| 5247 +/* This trick works on Sparc V8 CPUs with the Workshop compilers. */ |
| 5248 +#define MP_MUL_DxD(a, b, Phi, Plo) \ |
| 5249 + { unsigned long long product = (unsigned long long)a * b; \ |
| 5250 + Plo = (mp_digit)product; \ |
| 5251 + Phi = (mp_digit)(product >> MP_DIGIT_BIT); } |
| 5252 +#elif defined(OSF1) |
| 5253 +#define MP_MUL_DxD(a, b, Phi, Plo) \ |
| 5254 + { Plo = asm ("mulq %a0, %a1, %v0", a, b);\ |
| 5255 + Phi = asm ("umulh %a0, %a1, %v0", a, b); } |
| 5256 +#else |
| 5257 +#define MP_MUL_DxD(a, b, Phi, Plo) \ |
| 5258 + { mp_digit a0b1, a1b0; \ |
| 5259 + Plo = (a & MP_HALF_DIGIT_MAX) * (b & MP_HALF_DIGIT_MAX); \ |
| 5260 + Phi = (a >> MP_HALF_DIGIT_BIT) * (b >> MP_HALF_DIGIT_BIT); \ |
| 5261 + a0b1 = (a & MP_HALF_DIGIT_MAX) * (b >> MP_HALF_DIGIT_BIT); \ |
| 5262 + a1b0 = (a >> MP_HALF_DIGIT_BIT) * (b & MP_HALF_DIGIT_MAX); \ |
| 5263 + a1b0 += a0b1; \ |
| 5264 + Phi += a1b0 >> MP_HALF_DIGIT_BIT; \ |
| 5265 + if (a1b0 < a0b1) \ |
| 5266 + Phi += MP_HALF_RADIX; \ |
| 5267 + a1b0 <<= MP_HALF_DIGIT_BIT; \ |
| 5268 + Plo += a1b0; \ |
| 5269 + if (Plo < a1b0) \ |
| 5270 + ++Phi; \ |
| 5271 + } |
| 5272 +#endif |
| 5273 + |
| 5274 +#if !defined(MP_ASSEMBLY_MULTIPLY) |
| 5275 +/* c = a * b */ |
| 5276 +void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c) |
| 5277 +{ |
| 5278 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD) |
| 5279 + mp_digit d = 0; |
| 5280 + |
| 5281 + /* Inner product: Digits of a */ |
| 5282 + while (a_len--) { |
| 5283 + mp_word w = ((mp_word)b * *a++) + d; |
| 5284 + *c++ = ACCUM(w); |
| 5285 + d = CARRYOUT(w); |
| 5286 + } |
| 5287 + *c = d; |
| 5288 +#else |
| 5289 + mp_digit carry = 0; |
| 5290 + while (a_len--) { |
| 5291 + mp_digit a_i = *a++; |
| 5292 + mp_digit a0b0, a1b1; |
| 5293 + |
| 5294 + MP_MUL_DxD(a_i, b, a1b1, a0b0); |
| 5295 + |
| 5296 + a0b0 += carry; |
| 5297 + if (a0b0 < carry) |
| 5298 + ++a1b1; |
| 5299 + *c++ = a0b0; |
| 5300 + carry = a1b1; |
| 5301 + } |
| 5302 + *c = carry; |
| 5303 +#endif |
| 5304 +} |
| 5305 + |
| 5306 +/* c += a * b */ |
| 5307 +void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, |
| 5308 + mp_digit *c) |
| 5309 +{ |
| 5310 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD) |
| 5311 + mp_digit d = 0; |
| 5312 + |
| 5313 + /* Inner product: Digits of a */ |
| 5314 + while (a_len--) { |
| 5315 + mp_word w = ((mp_word)b * *a++) + *c + d; |
| 5316 + *c++ = ACCUM(w); |
| 5317 + d = CARRYOUT(w); |
| 5318 + } |
| 5319 + *c = d; |
| 5320 +#else |
| 5321 + mp_digit carry = 0; |
| 5322 + while (a_len--) { |
| 5323 + mp_digit a_i = *a++; |
| 5324 + mp_digit a0b0, a1b1; |
| 5325 + |
| 5326 + MP_MUL_DxD(a_i, b, a1b1, a0b0); |
| 5327 + |
| 5328 + a0b0 += carry; |
| 5329 + if (a0b0 < carry) |
| 5330 + ++a1b1; |
| 5331 + a0b0 += a_i = *c; |
| 5332 + if (a0b0 < a_i) |
| 5333 + ++a1b1; |
| 5334 + *c++ = a0b0; |
| 5335 + carry = a1b1; |
| 5336 + } |
| 5337 + *c = carry; |
| 5338 +#endif |
| 5339 +} |
| 5340 + |
| 5341 +/* Presently, this is only used by the Montgomery arithmetic code. */ |
| 5342 +/* c += a * b */ |
| 5343 +void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digi
t *c) |
| 5344 +{ |
| 5345 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD) |
| 5346 + mp_digit d = 0; |
| 5347 + |
| 5348 + /* Inner product: Digits of a */ |
| 5349 + while (a_len--) { |
| 5350 + mp_word w = ((mp_word)b * *a++) + *c + d; |
| 5351 + *c++ = ACCUM(w); |
| 5352 + d = CARRYOUT(w); |
| 5353 + } |
| 5354 + |
| 5355 + while (d) { |
| 5356 + mp_word w = (mp_word)*c + d; |
| 5357 + *c++ = ACCUM(w); |
| 5358 + d = CARRYOUT(w); |
| 5359 + } |
| 5360 +#else |
| 5361 + mp_digit carry = 0; |
| 5362 + while (a_len--) { |
| 5363 + mp_digit a_i = *a++; |
| 5364 + mp_digit a0b0, a1b1; |
| 5365 + |
| 5366 + MP_MUL_DxD(a_i, b, a1b1, a0b0); |
| 5367 + |
| 5368 + a0b0 += carry; |
| 5369 + if (a0b0 < carry) |
| 5370 + ++a1b1; |
| 5371 + |
| 5372 + a0b0 += a_i = *c; |
| 5373 + if (a0b0 < a_i) |
| 5374 + ++a1b1; |
| 5375 + |
| 5376 + *c++ = a0b0; |
| 5377 + carry = a1b1; |
| 5378 + } |
| 5379 + while (carry) { |
| 5380 + mp_digit c_i = *c; |
| 5381 + carry += c_i; |
| 5382 + *c++ = carry; |
| 5383 + carry = carry < c_i; |
| 5384 + } |
| 5385 +#endif |
| 5386 +} |
| 5387 +#endif |
| 5388 + |
| 5389 +#if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY) |
| 5390 +/* This trick works on Sparc V8 CPUs with the Workshop compilers. */ |
| 5391 +#define MP_SQR_D(a, Phi, Plo) \ |
| 5392 + { unsigned long long square = (unsigned long long)a * a; \ |
| 5393 + Plo = (mp_digit)square; \ |
| 5394 + Phi = (mp_digit)(square >> MP_DIGIT_BIT); } |
| 5395 +#elif defined(OSF1) |
| 5396 +#define MP_SQR_D(a, Phi, Plo) \ |
| 5397 + { Plo = asm ("mulq %a0, %a0, %v0", a);\ |
| 5398 + Phi = asm ("umulh %a0, %a0, %v0", a); } |
| 5399 +#else |
| 5400 +#define MP_SQR_D(a, Phi, Plo) \ |
| 5401 + { mp_digit Pmid; \ |
| 5402 + Plo = (a & MP_HALF_DIGIT_MAX) * (a & MP_HALF_DIGIT_MAX); \ |
| 5403 + Phi = (a >> MP_HALF_DIGIT_BIT) * (a >> MP_HALF_DIGIT_BIT); \ |
| 5404 + Pmid = (a & MP_HALF_DIGIT_MAX) * (a >> MP_HALF_DIGIT_BIT); \ |
| 5405 + Phi += Pmid >> (MP_HALF_DIGIT_BIT - 1); \ |
| 5406 + Pmid <<= (MP_HALF_DIGIT_BIT + 1); \ |
| 5407 + Plo += Pmid; \ |
| 5408 + if (Plo < Pmid) \ |
| 5409 + ++Phi; \ |
| 5410 + } |
| 5411 +#endif |
| 5412 + |
| 5413 +#if !defined(MP_ASSEMBLY_SQUARE) |
| 5414 +/* Add the squares of the digits of a to the digits of b. */ |
| 5415 +void s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps) |
| 5416 +{ |
| 5417 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD) |
| 5418 + mp_word w; |
| 5419 + mp_digit d; |
| 5420 + mp_size ix; |
| 5421 + |
| 5422 + w = 0; |
| 5423 +#define ADD_SQUARE(n) \ |
| 5424 + d = pa[n]; \ |
| 5425 + w += (d * (mp_word)d) + ps[2*n]; \ |
| 5426 + ps[2*n] = ACCUM(w); \ |
| 5427 + w = (w >> DIGIT_BIT) + ps[2*n+1]; \ |
| 5428 + ps[2*n+1] = ACCUM(w); \ |
| 5429 + w = (w >> DIGIT_BIT) |
| 5430 + |
| 5431 + for (ix = a_len; ix >= 4; ix -= 4) { |
| 5432 + ADD_SQUARE(0); |
| 5433 + ADD_SQUARE(1); |
| 5434 + ADD_SQUARE(2); |
| 5435 + ADD_SQUARE(3); |
| 5436 + pa += 4; |
| 5437 + ps += 8; |
| 5438 + } |
| 5439 + if (ix) { |
| 5440 + ps += 2*ix; |
| 5441 + pa += ix; |
| 5442 + switch (ix) { |
| 5443 + case 3: ADD_SQUARE(-3); /* FALLTHRU */ |
| 5444 + case 2: ADD_SQUARE(-2); /* FALLTHRU */ |
| 5445 + case 1: ADD_SQUARE(-1); /* FALLTHRU */ |
| 5446 + case 0: break; |
| 5447 + } |
| 5448 + } |
| 5449 + while (w) { |
| 5450 + w += *ps; |
| 5451 + *ps++ = ACCUM(w); |
| 5452 + w = (w >> DIGIT_BIT); |
| 5453 + } |
| 5454 +#else |
| 5455 + mp_digit carry = 0; |
| 5456 + while (a_len--) { |
| 5457 + mp_digit a_i = *pa++; |
| 5458 + mp_digit a0a0, a1a1; |
| 5459 + |
| 5460 + MP_SQR_D(a_i, a1a1, a0a0); |
| 5461 + |
| 5462 + /* here a1a1 and a0a0 constitute a_i ** 2 */ |
| 5463 + a0a0 += carry; |
| 5464 + if (a0a0 < carry) |
| 5465 + ++a1a1; |
| 5466 + |
| 5467 + /* now add to ps */ |
| 5468 + a0a0 += a_i = *ps; |
| 5469 + if (a0a0 < a_i) |
| 5470 + ++a1a1; |
| 5471 + *ps++ = a0a0; |
| 5472 + a1a1 += a_i = *ps; |
| 5473 + carry = (a1a1 < a_i); |
| 5474 + *ps++ = a1a1; |
| 5475 + } |
| 5476 + while (carry) { |
| 5477 + mp_digit s_i = *ps; |
| 5478 + carry += s_i; |
| 5479 + *ps++ = carry; |
| 5480 + carry = carry < s_i; |
| 5481 + } |
| 5482 +#endif |
| 5483 +} |
| 5484 +#endif |
| 5485 + |
| 5486 +#if (defined(MP_NO_MP_WORD) || defined(MP_NO_DIV_WORD)) \ |
| 5487 +&& !defined(MP_ASSEMBLY_DIV_2DX1D) |
| 5488 +/* |
| 5489 +** Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized |
| 5490 +** so its high bit is 1. This code is from NSPR. |
| 5491 +*/ |
| 5492 +mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor, |
| 5493 + mp_digit *qp, mp_digit *rp) |
| 5494 +{ |
| 5495 + mp_digit d1, d0, q1, q0; |
| 5496 + mp_digit r1, r0, m; |
| 5497 + |
| 5498 + d1 = divisor >> MP_HALF_DIGIT_BIT; |
| 5499 + d0 = divisor & MP_HALF_DIGIT_MAX; |
| 5500 + r1 = Nhi % d1; |
| 5501 + q1 = Nhi / d1; |
| 5502 + m = q1 * d0; |
| 5503 + r1 = (r1 << MP_HALF_DIGIT_BIT) | (Nlo >> MP_HALF_DIGIT_BIT); |
| 5504 + if (r1 < m) { |
| 5505 + q1--, r1 += divisor; |
| 5506 + if (r1 >= divisor && r1 < m) { |
| 5507 + q1--, r1 += divisor; |
| 5508 + } |
| 5509 + } |
| 5510 + r1 -= m; |
| 5511 + r0 = r1 % d1; |
| 5512 + q0 = r1 / d1; |
| 5513 + m = q0 * d0; |
| 5514 + r0 = (r0 << MP_HALF_DIGIT_BIT) | (Nlo & MP_HALF_DIGIT_MAX); |
| 5515 + if (r0 < m) { |
| 5516 + q0--, r0 += divisor; |
| 5517 + if (r0 >= divisor && r0 < m) { |
| 5518 + q0--, r0 += divisor; |
| 5519 + } |
| 5520 + } |
| 5521 + if (qp) |
| 5522 + *qp = (q1 << MP_HALF_DIGIT_BIT) | q0; |
| 5523 + if (rp) |
| 5524 + *rp = r0 - m; |
| 5525 + return MP_OKAY; |
| 5526 +} |
| 5527 +#endif |
| 5528 + |
| 5529 +#if MP_SQUARE |
| 5530 +/* {{{ s_mp_sqr(a) */ |
| 5531 + |
| 5532 +mp_err s_mp_sqr(mp_int *a) |
| 5533 +{ |
| 5534 + mp_err res; |
| 5535 + mp_int tmp; |
| 5536 + |
| 5537 + if((res = mp_init_size(&tmp, 2 * USED(a))) != MP_OKAY) |
| 5538 + return res; |
| 5539 + res = mp_sqr(a, &tmp); |
| 5540 + if (res == MP_OKAY) { |
| 5541 + s_mp_exch(&tmp, a); |
| 5542 + } |
| 5543 + mp_clear(&tmp); |
| 5544 + return res; |
| 5545 +} |
| 5546 + |
| 5547 +/* }}} */ |
| 5548 +#endif |
| 5549 + |
| 5550 +/* {{{ s_mp_div(a, b) */ |
| 5551 + |
| 5552 +/* |
| 5553 + s_mp_div(a, b) |
| 5554 + |
| 5555 + Compute a = a / b and b = a mod b. Assumes b > a. |
| 5556 + */ |
| 5557 + |
| 5558 +mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */ |
| 5559 + mp_int *div, /* i: divisor */ |
| 5560 + mp_int *quot) /* i: 0; o: quotient */ |
| 5561 +{ |
| 5562 + mp_int part, t; |
| 5563 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD) |
| 5564 + mp_word q_msd; |
| 5565 +#else |
| 5566 + mp_digit q_msd; |
| 5567 +#endif |
| 5568 + mp_err res; |
| 5569 + mp_digit d; |
| 5570 + mp_digit div_msd; |
| 5571 + int ix; |
| 5572 + |
| 5573 + if(mp_cmp_z(div) == 0) |
| 5574 + return MP_RANGE; |
| 5575 + |
| 5576 + /* Shortcut if divisor is power of two */ |
| 5577 + if((ix = s_mp_ispow2(div)) >= 0) { |
| 5578 + MP_CHECKOK( mp_copy(rem, quot) ); |
| 5579 + s_mp_div_2d(quot, (mp_digit)ix); |
| 5580 + s_mp_mod_2d(rem, (mp_digit)ix); |
| 5581 + |
| 5582 + return MP_OKAY; |
| 5583 + } |
| 5584 + |
| 5585 + DIGITS(&t) = 0; |
| 5586 + MP_SIGN(rem) = ZPOS; |
| 5587 + MP_SIGN(div) = ZPOS; |
| 5588 + |
| 5589 + /* A working temporary for division */ |
| 5590 + MP_CHECKOK( mp_init_size(&t, MP_ALLOC(rem))); |
| 5591 + |
| 5592 + /* Normalize to optimize guessing */ |
| 5593 + MP_CHECKOK( s_mp_norm(rem, div, &d) ); |
| 5594 + |
| 5595 + part = *rem; |
| 5596 + |
| 5597 + /* Perform the division itself...woo! */ |
| 5598 + MP_USED(quot) = MP_ALLOC(quot); |
| 5599 + |
| 5600 + /* Find a partial substring of rem which is at least div */ |
| 5601 + /* If we didn't find one, we're finished dividing */ |
| 5602 + while (MP_USED(rem) > MP_USED(div) || s_mp_cmp(rem, div) >= 0) { |
| 5603 + int i; |
| 5604 + int unusedRem; |
| 5605 + |
| 5606 + unusedRem = MP_USED(rem) - MP_USED(div); |
| 5607 + MP_DIGITS(&part) = MP_DIGITS(rem) + unusedRem; |
| 5608 + MP_ALLOC(&part) = MP_ALLOC(rem) - unusedRem; |
| 5609 + MP_USED(&part) = MP_USED(div); |
| 5610 + if (s_mp_cmp(&part, div) < 0) { |
| 5611 + -- unusedRem; |
| 5612 +#if MP_ARGCHK == 2 |
| 5613 + assert(unusedRem >= 0); |
| 5614 +#endif |
| 5615 + -- MP_DIGITS(&part); |
| 5616 + ++ MP_USED(&part); |
| 5617 + ++ MP_ALLOC(&part); |
| 5618 + } |
| 5619 + |
| 5620 + /* Compute a guess for the next quotient digit */ |
| 5621 + q_msd = MP_DIGIT(&part, MP_USED(&part) - 1); |
| 5622 + div_msd = MP_DIGIT(div, MP_USED(div) - 1); |
| 5623 + if (q_msd >= div_msd) { |
| 5624 + q_msd = 1; |
| 5625 + } else if (MP_USED(&part) > 1) { |
| 5626 +#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD) |
| 5627 + q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2); |
| 5628 + q_msd /= div_msd; |
| 5629 + if (q_msd == RADIX) |
| 5630 + --q_msd; |
| 5631 +#else |
| 5632 + mp_digit r; |
| 5633 + MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2), |
| 5634 + div_msd, &q_msd, &r) ); |
| 5635 +#endif |
| 5636 + } else { |
| 5637 + q_msd = 0; |
| 5638 + } |
| 5639 +#if MP_ARGCHK == 2 |
| 5640 + assert(q_msd > 0); /* This case should never occur any more. */ |
| 5641 +#endif |
| 5642 + if (q_msd <= 0) |
| 5643 + break; |
| 5644 + |
| 5645 + /* See what that multiplies out to */ |
| 5646 + mp_copy(div, &t); |
| 5647 + MP_CHECKOK( s_mp_mul_d(&t, (mp_digit)q_msd) ); |
| 5648 + |
| 5649 + /* |
| 5650 + If it's too big, back it off. We should not have to do this |
| 5651 + more than once, or, in rare cases, twice. Knuth describes a |
| 5652 + method by which this could be reduced to a maximum of once, but |
| 5653 + I didn't implement that here. |
| 5654 + * When using s_mpv_div_2dx1d, we may have to do this 3 times. |
| 5655 + */ |
| 5656 + for (i = 4; s_mp_cmp(&t, &part) > 0 && i > 0; --i) { |
| 5657 + --q_msd; |
| 5658 + s_mp_sub(&t, div); /* t -= div */ |
| 5659 + } |
| 5660 + if (i < 0) { |
| 5661 + res = MP_RANGE; |
| 5662 + goto CLEANUP; |
| 5663 + } |
| 5664 + |
| 5665 + /* At this point, q_msd should be the right next digit */ |
| 5666 + MP_CHECKOK( s_mp_sub(&part, &t) ); /* part -= t */ |
| 5667 + s_mp_clamp(rem); |
| 5668 + |
| 5669 + /* |
| 5670 + Include the digit in the quotient. We allocated enough memory |
| 5671 + for any quotient we could ever possibly get, so we should not |
| 5672 + have to check for failures here |
| 5673 + */ |
| 5674 + MP_DIGIT(quot, unusedRem) = (mp_digit)q_msd; |
| 5675 + } |
| 5676 + |
| 5677 + /* Denormalize remainder */ |
| 5678 + if (d) { |
| 5679 + s_mp_div_2d(rem, d); |
| 5680 + } |
| 5681 + |
| 5682 + s_mp_clamp(quot); |
| 5683 + |
| 5684 +CLEANUP: |
| 5685 + mp_clear(&t); |
| 5686 + |
| 5687 + return res; |
| 5688 + |
| 5689 +} /* end s_mp_div() */ |
| 5690 + |
| 5691 + |
| 5692 +/* }}} */ |
| 5693 + |
| 5694 +/* {{{ s_mp_2expt(a, k) */ |
| 5695 + |
| 5696 +mp_err s_mp_2expt(mp_int *a, mp_digit k) |
| 5697 +{ |
| 5698 + mp_err res; |
| 5699 + mp_size dig, bit; |
| 5700 + |
| 5701 + dig = k / DIGIT_BIT; |
| 5702 + bit = k % DIGIT_BIT; |
| 5703 + |
| 5704 + mp_zero(a); |
| 5705 + if((res = s_mp_pad(a, dig + 1)) != MP_OKAY) |
| 5706 + return res; |
| 5707 + |
| 5708 + DIGIT(a, dig) |= ((mp_digit)1 << bit); |
| 5709 + |
| 5710 + return MP_OKAY; |
| 5711 + |
| 5712 +} /* end s_mp_2expt() */ |
| 5713 + |
| 5714 +/* }}} */ |
| 5715 + |
| 5716 +/* {{{ s_mp_reduce(x, m, mu) */ |
| 5717 + |
| 5718 +/* |
| 5719 + Compute Barrett reduction, x (mod m), given a precomputed value for |
| 5720 + mu = b^2k / m, where b = RADIX and k = #digits(m). This should be |
| 5721 + faster than straight division, when many reductions by the same |
| 5722 + value of m are required (such as in modular exponentiation). This |
| 5723 + can nearly halve the time required to do modular exponentiation, |
| 5724 + as compared to using the full integer divide to reduce. |
| 5725 + |
| 5726 + This algorithm was derived from the _Handbook of Applied |
| 5727 + Cryptography_ by Menezes, Oorschot and VanStone, Ch. 14, |
| 5728 + pp. 603-604. |
| 5729 + */ |
| 5730 + |
| 5731 +mp_err s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) |
| 5732 +{ |
| 5733 + mp_int q; |
| 5734 + mp_err res; |
| 5735 + |
| 5736 + if((res = mp_init_copy(&q, x)) != MP_OKAY) |
| 5737 + return res; |
| 5738 + |
| 5739 + s_mp_rshd(&q, USED(m) - 1); /* q1 = x / b^(k-1) */ |
| 5740 + s_mp_mul(&q, mu); /* q2 = q1 * mu */ |
| 5741 + s_mp_rshd(&q, USED(m) + 1); /* q3 = q2 / b^(k+1) */ |
| 5742 + |
| 5743 + /* x = x mod b^(k+1), quick (no division) */ |
| 5744 + s_mp_mod_2d(x, DIGIT_BIT * (USED(m) + 1)); |
| 5745 + |
| 5746 + /* q = q * m mod b^(k+1), quick (no division) */ |
| 5747 + s_mp_mul(&q, m); |
| 5748 + s_mp_mod_2d(&q, DIGIT_BIT * (USED(m) + 1)); |
| 5749 + |
| 5750 + /* x = x - q */ |
| 5751 + if((res = mp_sub(x, &q, x)) != MP_OKAY) |
| 5752 + goto CLEANUP; |
| 5753 + |
| 5754 + /* If x < 0, add b^(k+1) to it */ |
| 5755 + if(mp_cmp_z(x) < 0) { |
| 5756 + mp_set(&q, 1); |
| 5757 + if((res = s_mp_lshd(&q, USED(m) + 1)) != MP_OKAY) |
| 5758 + goto CLEANUP; |
| 5759 + if((res = mp_add(x, &q, x)) != MP_OKAY) |
| 5760 + goto CLEANUP; |
| 5761 + } |
| 5762 + |
| 5763 + /* Back off if it's too big */ |
| 5764 + while(mp_cmp(x, m) >= 0) { |
| 5765 + if((res = s_mp_sub(x, m)) != MP_OKAY) |
| 5766 + break; |
| 5767 + } |
| 5768 + |
| 5769 + CLEANUP: |
| 5770 + mp_clear(&q); |
| 5771 + |
| 5772 + return res; |
| 5773 + |
| 5774 +} /* end s_mp_reduce() */ |
| 5775 + |
| 5776 +/* }}} */ |
| 5777 + |
| 5778 +/* }}} */ |
| 5779 + |
| 5780 +/* {{{ Primitive comparisons */ |
| 5781 + |
| 5782 +/* {{{ s_mp_cmp(a, b) */ |
| 5783 + |
| 5784 +/* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b */ |
| 5785 +int s_mp_cmp(const mp_int *a, const mp_int *b) |
| 5786 +{ |
| 5787 + mp_size used_a = MP_USED(a); |
| 5788 + { |
| 5789 + mp_size used_b = MP_USED(b); |
| 5790 + |
| 5791 + if (used_a > used_b) |
| 5792 + goto IS_GT; |
| 5793 + if (used_a < used_b) |
| 5794 + goto IS_LT; |
| 5795 + } |
| 5796 + { |
| 5797 + mp_digit *pa, *pb; |
| 5798 + mp_digit da = 0, db = 0; |
| 5799 + |
| 5800 +#define CMP_AB(n) if ((da = pa[n]) != (db = pb[n])) goto done |
| 5801 + |
| 5802 + pa = MP_DIGITS(a) + used_a; |
| 5803 + pb = MP_DIGITS(b) + used_a; |
| 5804 + while (used_a >= 4) { |
| 5805 + pa -= 4; |
| 5806 + pb -= 4; |
| 5807 + used_a -= 4; |
| 5808 + CMP_AB(3); |
| 5809 + CMP_AB(2); |
| 5810 + CMP_AB(1); |
| 5811 + CMP_AB(0); |
| 5812 + } |
| 5813 + while (used_a-- > 0 && ((da = *--pa) == (db = *--pb))) |
| 5814 + /* do nothing */; |
| 5815 +done: |
| 5816 + if (da > db) |
| 5817 + goto IS_GT; |
| 5818 + if (da < db) |
| 5819 + goto IS_LT; |
| 5820 + } |
| 5821 + return MP_EQ; |
| 5822 +IS_LT: |
| 5823 + return MP_LT; |
| 5824 +IS_GT: |
| 5825 + return MP_GT; |
| 5826 +} /* end s_mp_cmp() */ |
| 5827 + |
| 5828 +/* }}} */ |
| 5829 + |
| 5830 +/* {{{ s_mp_cmp_d(a, d) */ |
| 5831 + |
| 5832 +/* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d */ |
| 5833 +int s_mp_cmp_d(const mp_int *a, mp_digit d) |
| 5834 +{ |
| 5835 + if(USED(a) > 1) |
| 5836 + return MP_GT; |
| 5837 + |
| 5838 + if(DIGIT(a, 0) < d) |
| 5839 + return MP_LT; |
| 5840 + else if(DIGIT(a, 0) > d) |
| 5841 + return MP_GT; |
| 5842 + else |
| 5843 + return MP_EQ; |
| 5844 + |
| 5845 +} /* end s_mp_cmp_d() */ |
| 5846 + |
| 5847 +/* }}} */ |
| 5848 + |
| 5849 +/* {{{ s_mp_ispow2(v) */ |
| 5850 + |
| 5851 +/* |
| 5852 + Returns -1 if the value is not a power of two; otherwise, it returns |
| 5853 + k such that v = 2^k, i.e. lg(v). |
| 5854 + */ |
| 5855 +int s_mp_ispow2(const mp_int *v) |
| 5856 +{ |
| 5857 + mp_digit d; |
| 5858 + int extra = 0, ix; |
| 5859 + |
| 5860 + ix = MP_USED(v) - 1; |
| 5861 + d = MP_DIGIT(v, ix); /* most significant digit of v */ |
| 5862 + |
| 5863 + extra = s_mp_ispow2d(d); |
| 5864 + if (extra < 0 || ix == 0) |
| 5865 + return extra; |
| 5866 + |
| 5867 + while (--ix >= 0) { |
| 5868 + if (DIGIT(v, ix) != 0) |
| 5869 + return -1; /* not a power of two */ |
| 5870 + extra += MP_DIGIT_BIT; |
| 5871 + } |
| 5872 + |
| 5873 + return extra; |
| 5874 + |
| 5875 +} /* end s_mp_ispow2() */ |
| 5876 + |
| 5877 +/* }}} */ |
| 5878 + |
| 5879 +/* {{{ s_mp_ispow2d(d) */ |
| 5880 + |
| 5881 +int s_mp_ispow2d(mp_digit d) |
| 5882 +{ |
| 5883 + if ((d != 0) && ((d & (d-1)) == 0)) { /* d is a power of 2 */ |
| 5884 + int pow = 0; |
| 5885 +#if defined (MP_USE_UINT_DIGIT) |
| 5886 + if (d & 0xffff0000U) |
| 5887 + pow += 16; |
| 5888 + if (d & 0xff00ff00U) |
| 5889 + pow += 8; |
| 5890 + if (d & 0xf0f0f0f0U) |
| 5891 + pow += 4; |
| 5892 + if (d & 0xccccccccU) |
| 5893 + pow += 2; |
| 5894 + if (d & 0xaaaaaaaaU) |
| 5895 + pow += 1; |
| 5896 +#elif defined(MP_USE_LONG_LONG_DIGIT) |
| 5897 + if (d & 0xffffffff00000000ULL) |
| 5898 + pow += 32; |
| 5899 + if (d & 0xffff0000ffff0000ULL) |
| 5900 + pow += 16; |
| 5901 + if (d & 0xff00ff00ff00ff00ULL) |
| 5902 + pow += 8; |
| 5903 + if (d & 0xf0f0f0f0f0f0f0f0ULL) |
| 5904 + pow += 4; |
| 5905 + if (d & 0xccccccccccccccccULL) |
| 5906 + pow += 2; |
| 5907 + if (d & 0xaaaaaaaaaaaaaaaaULL) |
| 5908 + pow += 1; |
| 5909 +#elif defined(MP_USE_LONG_DIGIT) |
| 5910 + if (d & 0xffffffff00000000UL) |
| 5911 + pow += 32; |
| 5912 + if (d & 0xffff0000ffff0000UL) |
| 5913 + pow += 16; |
| 5914 + if (d & 0xff00ff00ff00ff00UL) |
| 5915 + pow += 8; |
| 5916 + if (d & 0xf0f0f0f0f0f0f0f0UL) |
| 5917 + pow += 4; |
| 5918 + if (d & 0xccccccccccccccccUL) |
| 5919 + pow += 2; |
| 5920 + if (d & 0xaaaaaaaaaaaaaaaaUL) |
| 5921 + pow += 1; |
| 5922 +#else |
| 5923 +#error "unknown type for mp_digit" |
| 5924 +#endif |
| 5925 + return pow; |
| 5926 + } |
| 5927 + return -1; |
| 5928 + |
| 5929 +} /* end s_mp_ispow2d() */ |
| 5930 + |
| 5931 +/* }}} */ |
| 5932 + |
| 5933 +/* }}} */ |
| 5934 + |
| 5935 +/* {{{ Primitive I/O helpers */ |
| 5936 + |
| 5937 +/* {{{ s_mp_tovalue(ch, r) */ |
| 5938 + |
| 5939 +/* |
| 5940 + Convert the given character to its digit value, in the given radix. |
| 5941 + If the given character is not understood in the given radix, -1 is |
| 5942 + returned. Otherwise the digit's numeric value is returned. |
| 5943 + |
| 5944 + The results will be odd if you use a radix < 2 or > 62, you are |
| 5945 + expected to know what you're up to. |
| 5946 + */ |
| 5947 +int s_mp_tovalue(char ch, int r) |
| 5948 +{ |
| 5949 + int val, xch; |
| 5950 + |
| 5951 + if(r > 36) |
| 5952 + xch = ch; |
| 5953 + else |
| 5954 + xch = toupper(ch); |
| 5955 + |
| 5956 + if(isdigit(xch)) |
| 5957 + val = xch - '0'; |
| 5958 + else if(isupper(xch)) |
| 5959 + val = xch - 'A' + 10; |
| 5960 + else if(islower(xch)) |
| 5961 + val = xch - 'a' + 36; |
| 5962 + else if(xch == '+') |
| 5963 + val = 62; |
| 5964 + else if(xch == '/') |
| 5965 + val = 63; |
| 5966 + else |
| 5967 + return -1; |
| 5968 + |
| 5969 + if(val < 0 || val >= r) |
| 5970 + return -1; |
| 5971 + |
| 5972 + return val; |
| 5973 + |
| 5974 +} /* end s_mp_tovalue() */ |
| 5975 + |
| 5976 +/* }}} */ |
| 5977 + |
| 5978 +/* {{{ s_mp_todigit(val, r, low) */ |
| 5979 + |
| 5980 +/* |
| 5981 + Convert val to a radix-r digit, if possible. If val is out of range |
| 5982 + for r, returns zero. Otherwise, returns an ASCII character denoting |
| 5983 + the value in the given radix. |
| 5984 + |
| 5985 + The results may be odd if you use a radix < 2 or > 64, you are |
| 5986 + expected to know what you're doing. |
| 5987 + */ |
| 5988 + |
| 5989 +char s_mp_todigit(mp_digit val, int r, int low) |
| 5990 +{ |
| 5991 + char ch; |
| 5992 + |
| 5993 + if(val >= r) |
| 5994 + return 0; |
| 5995 + |
| 5996 + ch = s_dmap_1[val]; |
| 5997 + |
| 5998 + if(r <= 36 && low) |
| 5999 + ch = tolower(ch); |
| 6000 + |
| 6001 + return ch; |
| 6002 + |
| 6003 +} /* end s_mp_todigit() */ |
| 6004 + |
| 6005 +/* }}} */ |
| 6006 + |
| 6007 +/* {{{ s_mp_outlen(bits, radix) */ |
| 6008 + |
| 6009 +/* |
| 6010 + Return an estimate for how long a string is needed to hold a radix |
| 6011 + r representation of a number with 'bits' significant bits, plus an |
| 6012 + extra for a zero terminator (assuming C style strings here) |
| 6013 + */ |
| 6014 +int s_mp_outlen(int bits, int r) |
| 6015 +{ |
| 6016 + return (int)((double)bits * LOG_V_2(r) + 1.5) + 1; |
| 6017 + |
| 6018 +} /* end s_mp_outlen() */ |
| 6019 + |
| 6020 +/* }}} */ |
| 6021 + |
| 6022 +/* }}} */ |
| 6023 + |
| 6024 +/* {{{ mp_read_unsigned_octets(mp, str, len) */ |
| 6025 +/* mp_read_unsigned_octets(mp, str, len) |
| 6026 + Read in a raw value (base 256) into the given mp_int |
| 6027 + No sign bit, number is positive. Leading zeros ignored. |
| 6028 + */ |
| 6029 + |
| 6030 +mp_err |
| 6031 +mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len) |
| 6032 +{ |
| 6033 + int count; |
| 6034 + mp_err res; |
| 6035 + mp_digit d; |
| 6036 + |
| 6037 + ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG); |
| 6038 + |
| 6039 + mp_zero(mp); |
| 6040 + |
| 6041 + count = len % sizeof(mp_digit); |
| 6042 + if (count) { |
| 6043 + for (d = 0; count-- > 0; --len) { |
| 6044 + d = (d << 8) | *str++; |
| 6045 + } |
| 6046 + MP_DIGIT(mp, 0) = d; |
| 6047 + } |
| 6048 + |
| 6049 + /* Read the rest of the digits */ |
| 6050 + for(; len > 0; len -= sizeof(mp_digit)) { |
| 6051 + for (d = 0, count = sizeof(mp_digit); count > 0; --count) { |
| 6052 + d = (d << 8) | *str++; |
| 6053 + } |
| 6054 + if (MP_EQ == mp_cmp_z(mp)) { |
| 6055 + if (!d) |
| 6056 + continue; |
| 6057 + } else { |
| 6058 + if((res = s_mp_lshd(mp, 1)) != MP_OKAY) |
| 6059 + return res; |
| 6060 + } |
| 6061 + MP_DIGIT(mp, 0) = d; |
| 6062 + } |
| 6063 + return MP_OKAY; |
| 6064 +} /* end mp_read_unsigned_octets() */ |
| 6065 +/* }}} */ |
| 6066 + |
| 6067 +/* {{{ mp_unsigned_octet_size(mp) */ |
| 6068 +int |
| 6069 +mp_unsigned_octet_size(const mp_int *mp) |
| 6070 +{ |
| 6071 + int bytes; |
| 6072 + int ix; |
| 6073 + mp_digit d = 0; |
| 6074 + |
| 6075 + ARGCHK(mp != NULL, MP_BADARG); |
| 6076 + ARGCHK(MP_ZPOS == SIGN(mp), MP_BADARG); |
| 6077 + |
| 6078 + bytes = (USED(mp) * sizeof(mp_digit)); |
| 6079 + |
| 6080 + /* subtract leading zeros. */ |
| 6081 + /* Iterate over each digit... */ |
| 6082 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 6083 + d = DIGIT(mp, ix); |
| 6084 + if (d) |
| 6085 + break; |
| 6086 + bytes -= sizeof(d); |
| 6087 + } |
| 6088 + if (!bytes) |
| 6089 + return 1; |
| 6090 + |
| 6091 + /* Have MSD, check digit bytes, high order first */ |
| 6092 + for(ix = sizeof(mp_digit) - 1; ix >= 0; ix--) { |
| 6093 + unsigned char x = (unsigned char)(d >> (ix * CHAR_BIT)); |
| 6094 + if (x) |
| 6095 + break; |
| 6096 + --bytes; |
| 6097 + } |
| 6098 + return bytes; |
| 6099 +} /* end mp_unsigned_octet_size() */ |
| 6100 +/* }}} */ |
| 6101 + |
| 6102 +/* {{{ mp_to_unsigned_octets(mp, str) */ |
| 6103 +/* output a buffer of big endian octets no longer than specified. */ |
| 6104 +mp_err |
| 6105 +mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen) |
| 6106 +{ |
| 6107 + int ix, pos = 0; |
| 6108 + int bytes; |
| 6109 + |
| 6110 + ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG); |
| 6111 + |
| 6112 + bytes = mp_unsigned_octet_size(mp); |
| 6113 + ARGCHK(bytes <= maxlen, MP_BADARG); |
| 6114 + |
| 6115 + /* Iterate over each digit... */ |
| 6116 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 6117 + mp_digit d = DIGIT(mp, ix); |
| 6118 + int jx; |
| 6119 + |
| 6120 + /* Unpack digit bytes, high order first */ |
| 6121 + for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) { |
| 6122 + unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT)); |
| 6123 + if (!pos && !x) /* suppress leading zeros */ |
| 6124 + continue; |
| 6125 + str[pos++] = x; |
| 6126 + } |
| 6127 + } |
| 6128 + if (!pos) |
| 6129 + str[pos++] = 0; |
| 6130 + return pos; |
| 6131 +} /* end mp_to_unsigned_octets() */ |
| 6132 +/* }}} */ |
| 6133 + |
| 6134 +/* {{{ mp_to_signed_octets(mp, str) */ |
| 6135 +/* output a buffer of big endian octets no longer than specified. */ |
| 6136 +mp_err |
| 6137 +mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen) |
| 6138 +{ |
| 6139 + int ix, pos = 0; |
| 6140 + int bytes; |
| 6141 + |
| 6142 + ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG); |
| 6143 + |
| 6144 + bytes = mp_unsigned_octet_size(mp); |
| 6145 + ARGCHK(bytes <= maxlen, MP_BADARG); |
| 6146 + |
| 6147 + /* Iterate over each digit... */ |
| 6148 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 6149 + mp_digit d = DIGIT(mp, ix); |
| 6150 + int jx; |
| 6151 + |
| 6152 + /* Unpack digit bytes, high order first */ |
| 6153 + for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) { |
| 6154 + unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT)); |
| 6155 + if (!pos) { |
| 6156 + if (!x) /* suppress leading zeros */ |
| 6157 + continue; |
| 6158 + if (x & 0x80) { /* add one leading zero to make output positive. */ |
| 6159 + ARGCHK(bytes + 1 <= maxlen, MP_BADARG); |
| 6160 + if (bytes + 1 > maxlen) |
| 6161 + return MP_BADARG; |
| 6162 + str[pos++] = 0; |
| 6163 + } |
| 6164 + } |
| 6165 + str[pos++] = x; |
| 6166 + } |
| 6167 + } |
| 6168 + if (!pos) |
| 6169 + str[pos++] = 0; |
| 6170 + return pos; |
| 6171 +} /* end mp_to_signed_octets() */ |
| 6172 +/* }}} */ |
| 6173 + |
| 6174 +/* {{{ mp_to_fixlen_octets(mp, str) */ |
| 6175 +/* output a buffer of big endian octets exactly as long as requested. */ |
| 6176 +mp_err |
| 6177 +mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length) |
| 6178 +{ |
| 6179 + int ix, pos = 0; |
| 6180 + int bytes; |
| 6181 + |
| 6182 + ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG); |
| 6183 + |
| 6184 + bytes = mp_unsigned_octet_size(mp); |
| 6185 + ARGCHK(bytes <= length, MP_BADARG); |
| 6186 + |
| 6187 + /* place any needed leading zeros */ |
| 6188 + for (;length > bytes; --length) { |
| 6189 + *str++ = 0; |
| 6190 + } |
| 6191 + |
| 6192 + /* Iterate over each digit... */ |
| 6193 + for(ix = USED(mp) - 1; ix >= 0; ix--) { |
| 6194 + mp_digit d = DIGIT(mp, ix); |
| 6195 + int jx; |
| 6196 + |
| 6197 + /* Unpack digit bytes, high order first */ |
| 6198 + for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) { |
| 6199 + unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT)); |
| 6200 + if (!pos && !x) /* suppress leading zeros */ |
| 6201 + continue; |
| 6202 + str[pos++] = x; |
| 6203 + } |
| 6204 + } |
| 6205 + if (!pos) |
| 6206 + str[pos++] = 0; |
| 6207 + return MP_OKAY; |
| 6208 +} /* end mp_to_fixlen_octets() */ |
| 6209 +/* }}} */ |
| 6210 + |
| 6211 + |
| 6212 +/*------------------------------------------------------------------------*/ |
| 6213 +/* HERE THERE BE DRAGONS */ |
| 6214 + |
| 6215 diff --git a/net/third_party/nss/ssl/mpi/mpi.h b/net/third_party/nss/ssl/mpi/mpi
.h |
| 6216 new file mode 100644 |
| 6217 index 0000000..79503f3 |
| 6218 --- /dev/null |
| 6219 +++ b/net/third_party/nss/ssl/mpi/mpi.h |
| 6220 @@ -0,0 +1,340 @@ |
| 6221 +/* |
| 6222 + * mpi.h |
| 6223 + * |
| 6224 + * Arbitrary precision integer arithmetic library |
| 6225 + * |
| 6226 + * ***** BEGIN LICENSE BLOCK ***** |
| 6227 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 6228 + * |
| 6229 + * The contents of this file are subject to the Mozilla Public License Version |
| 6230 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 6231 + * the License. You may obtain a copy of the License at |
| 6232 + * http://www.mozilla.org/MPL/ |
| 6233 + * |
| 6234 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 6235 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 6236 + * for the specific language governing rights and limitations under the |
| 6237 + * License. |
| 6238 + * |
| 6239 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 6240 + * |
| 6241 + * The Initial Developer of the Original Code is |
| 6242 + * Michael J. Fromberger. |
| 6243 + * Portions created by the Initial Developer are Copyright (C) 1998 |
| 6244 + * the Initial Developer. All Rights Reserved. |
| 6245 + * |
| 6246 + * Contributor(s): |
| 6247 + * Netscape Communications Corporation |
| 6248 + * |
| 6249 + * Alternatively, the contents of this file may be used under the terms of |
| 6250 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 6251 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 6252 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 6253 + * of those above. If you wish to allow use of your version of this file only |
| 6254 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 6255 + * use your version of this file under the terms of the MPL, indicate your |
| 6256 + * decision by deleting the provisions above and replace them with the notice |
| 6257 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 6258 + * the provisions above, a recipient may use your version of this file under |
| 6259 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 6260 + * |
| 6261 + * ***** END LICENSE BLOCK ***** */ |
| 6262 +/* $Id: mpi.h,v 1.23 2008/12/04 18:16:34 rrelyea%redhat.com Exp $ */ |
| 6263 + |
| 6264 +#ifndef _H_MPI_ |
| 6265 +#define _H_MPI_ |
| 6266 + |
| 6267 +#include "mpi-config.h" |
| 6268 + |
| 6269 +#if MP_DEBUG |
| 6270 +#undef MP_IOFUNC |
| 6271 +#define MP_IOFUNC 1 |
| 6272 +#endif |
| 6273 + |
| 6274 +#if MP_IOFUNC |
| 6275 +#include <stdio.h> |
| 6276 +#include <ctype.h> |
| 6277 +#endif |
| 6278 + |
| 6279 +#include <limits.h> |
| 6280 + |
| 6281 +#if defined(BSDI) |
| 6282 +#undef ULLONG_MAX |
| 6283 +#endif |
| 6284 + |
| 6285 +#if defined( macintosh ) |
| 6286 +#include <Types.h> |
| 6287 +#elif defined( _WIN32_WCE) |
| 6288 +/* #include <sys/types.h> What do we need here ?? */ |
| 6289 +#else |
| 6290 +#include <sys/types.h> |
| 6291 +#endif |
| 6292 + |
| 6293 +#define MP_NEG 1 |
| 6294 +#define MP_ZPOS 0 |
| 6295 + |
| 6296 +#define MP_OKAY 0 /* no error, all is well */ |
| 6297 +#define MP_YES 0 /* yes (boolean result) */ |
| 6298 +#define MP_NO -1 /* no (boolean result) */ |
| 6299 +#define MP_MEM -2 /* out of memory */ |
| 6300 +#define MP_RANGE -3 /* argument out of range */ |
| 6301 +#define MP_BADARG -4 /* invalid parameter */ |
| 6302 +#define MP_UNDEF -5 /* answer is undefined */ |
| 6303 +#define MP_LAST_CODE MP_UNDEF |
| 6304 + |
| 6305 +typedef unsigned int mp_sign; |
| 6306 +typedef unsigned int mp_size; |
| 6307 +typedef int mp_err; |
| 6308 + |
| 6309 +#define MP_32BIT_MAX 4294967295U |
| 6310 + |
| 6311 +#if !defined(ULONG_MAX) |
| 6312 +#error "ULONG_MAX not defined" |
| 6313 +#elif !defined(UINT_MAX) |
| 6314 +#error "UINT_MAX not defined" |
| 6315 +#elif !defined(USHRT_MAX) |
| 6316 +#error "USHRT_MAX not defined" |
| 6317 +#endif |
| 6318 + |
| 6319 +#if defined(ULONG_LONG_MAX) /* GCC, HPUX */ |
| 6320 +#define MP_ULONG_LONG_MAX ULONG_LONG_MAX |
| 6321 +#elif defined(ULLONG_MAX) /* Solaris */ |
| 6322 +#define MP_ULONG_LONG_MAX ULLONG_MAX |
| 6323 +/* MP_ULONG_LONG_MAX was defined to be ULLONG_MAX */ |
| 6324 +#elif defined(ULONGLONG_MAX) /* IRIX, AIX */ |
| 6325 +#define MP_ULONG_LONG_MAX ULONGLONG_MAX |
| 6326 +#endif |
| 6327 + |
| 6328 +/* We only use unsigned long for mp_digit iff long is more than 32 bits. */ |
| 6329 +#if !defined(MP_USE_UINT_DIGIT) && ULONG_MAX > MP_32BIT_MAX |
| 6330 +typedef unsigned long mp_digit; |
| 6331 +#define MP_DIGIT_MAX ULONG_MAX |
| 6332 +#define MP_DIGIT_FMT "%016lX" /* printf() format for 1 digit */ |
| 6333 +#define MP_HALF_DIGIT_MAX UINT_MAX |
| 6334 +#undef MP_NO_MP_WORD |
| 6335 +#define MP_NO_MP_WORD 1 |
| 6336 +#undef MP_USE_LONG_DIGIT |
| 6337 +#define MP_USE_LONG_DIGIT 1 |
| 6338 +#undef MP_USE_LONG_LONG_DIGIT |
| 6339 + |
| 6340 +#elif !defined(MP_USE_UINT_DIGIT) && defined(MP_ULONG_LONG_MAX) |
| 6341 +typedef unsigned long long mp_digit; |
| 6342 +#define MP_DIGIT_MAX MP_ULONG_LONG_MAX |
| 6343 +#define MP_DIGIT_FMT "%016llX" /* printf() format for 1 digit */ |
| 6344 +#define MP_HALF_DIGIT_MAX UINT_MAX |
| 6345 +#undef MP_NO_MP_WORD |
| 6346 +#define MP_NO_MP_WORD 1 |
| 6347 +#undef MP_USE_LONG_LONG_DIGIT |
| 6348 +#define MP_USE_LONG_LONG_DIGIT 1 |
| 6349 +#undef MP_USE_LONG_DIGIT |
| 6350 + |
| 6351 +#else |
| 6352 +typedef unsigned int mp_digit; |
| 6353 +#define MP_DIGIT_MAX UINT_MAX |
| 6354 +#define MP_DIGIT_FMT "%08X" /* printf() format for 1 digit */ |
| 6355 +#define MP_HALF_DIGIT_MAX USHRT_MAX |
| 6356 +#undef MP_USE_UINT_DIGIT |
| 6357 +#define MP_USE_UINT_DIGIT 1 |
| 6358 +#undef MP_USE_LONG_LONG_DIGIT |
| 6359 +#undef MP_USE_LONG_DIGIT |
| 6360 +#endif |
| 6361 + |
| 6362 +#if !defined(MP_NO_MP_WORD) |
| 6363 +#if defined(MP_USE_UINT_DIGIT) && \ |
| 6364 + (defined(MP_ULONG_LONG_MAX) || (ULONG_MAX > UINT_MAX)) |
| 6365 + |
| 6366 +#if (ULONG_MAX > UINT_MAX) |
| 6367 +typedef unsigned long mp_word; |
| 6368 +typedef long mp_sword; |
| 6369 +#define MP_WORD_MAX ULONG_MAX |
| 6370 + |
| 6371 +#else |
| 6372 +typedef unsigned long long mp_word; |
| 6373 +typedef long long mp_sword; |
| 6374 +#define MP_WORD_MAX MP_ULONG_LONG_MAX |
| 6375 +#endif |
| 6376 + |
| 6377 +#else |
| 6378 +#define MP_NO_MP_WORD 1 |
| 6379 +#endif |
| 6380 +#endif /* !defined(MP_NO_MP_WORD) */ |
| 6381 + |
| 6382 +#if !defined(MP_WORD_MAX) && defined(MP_DEFINE_SMALL_WORD) |
| 6383 +typedef unsigned int mp_word; |
| 6384 +typedef int mp_sword; |
| 6385 +#define MP_WORD_MAX UINT_MAX |
| 6386 +#endif |
| 6387 + |
| 6388 +#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit)) |
| 6389 +#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word)) |
| 6390 +#define MP_RADIX (1+(mp_word)MP_DIGIT_MAX) |
| 6391 + |
| 6392 +#define MP_HALF_DIGIT_BIT (MP_DIGIT_BIT/2) |
| 6393 +#define MP_HALF_RADIX (1+(mp_digit)MP_HALF_DIGIT_MAX) |
| 6394 +/* MP_HALF_RADIX really ought to be called MP_SQRT_RADIX, but it's named |
| 6395 +** MP_HALF_RADIX because it's the radix for MP_HALF_DIGITs, and it's |
| 6396 +** consistent with the other _HALF_ names. |
| 6397 +*/ |
| 6398 + |
| 6399 + |
| 6400 +/* Macros for accessing the mp_int internals */ |
| 6401 +#define MP_SIGN(MP) ((MP)->sign) |
| 6402 +#define MP_USED(MP) ((MP)->used) |
| 6403 +#define MP_ALLOC(MP) ((MP)->alloc) |
| 6404 +#define MP_DIGITS(MP) ((MP)->dp) |
| 6405 +#define MP_DIGIT(MP,N) (MP)->dp[(N)] |
| 6406 + |
| 6407 +/* This defines the maximum I/O base (minimum is 2) */ |
| 6408 +#define MP_MAX_RADIX 64 |
| 6409 + |
| 6410 +typedef struct { |
| 6411 + mp_sign sign; /* sign of this quantity */ |
| 6412 + mp_size alloc; /* how many digits allocated */ |
| 6413 + mp_size used; /* how many digits used */ |
| 6414 + mp_digit *dp; /* the digits themselves */ |
| 6415 +} mp_int; |
| 6416 + |
| 6417 +/* Default precision */ |
| 6418 +mp_size mp_get_prec(void); |
| 6419 +void mp_set_prec(mp_size prec); |
| 6420 + |
| 6421 +/* Memory management */ |
| 6422 +mp_err mp_init(mp_int *mp); |
| 6423 +mp_err mp_init_size(mp_int *mp, mp_size prec); |
| 6424 +mp_err mp_init_copy(mp_int *mp, const mp_int *from); |
| 6425 +mp_err mp_copy(const mp_int *from, mp_int *to); |
| 6426 +void mp_exch(mp_int *mp1, mp_int *mp2); |
| 6427 +void mp_clear(mp_int *mp); |
| 6428 +void mp_zero(mp_int *mp); |
| 6429 +void mp_set(mp_int *mp, mp_digit d); |
| 6430 +mp_err mp_set_int(mp_int *mp, long z); |
| 6431 +#define mp_set_long(mp,z) mp_set_int(mp,z) |
| 6432 +mp_err mp_set_ulong(mp_int *mp, unsigned long z); |
| 6433 + |
| 6434 +/* Single digit arithmetic */ |
| 6435 +mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b); |
| 6436 +mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b); |
| 6437 +mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b); |
| 6438 +mp_err mp_mul_2(const mp_int *a, mp_int *c); |
| 6439 +mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r); |
| 6440 +mp_err mp_div_2(const mp_int *a, mp_int *c); |
| 6441 +mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c); |
| 6442 + |
| 6443 +/* Sign manipulations */ |
| 6444 +mp_err mp_abs(const mp_int *a, mp_int *b); |
| 6445 +mp_err mp_neg(const mp_int *a, mp_int *b); |
| 6446 + |
| 6447 +/* Full arithmetic */ |
| 6448 +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c); |
| 6449 +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c); |
| 6450 +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c); |
| 6451 +#if MP_SQUARE |
| 6452 +mp_err mp_sqr(const mp_int *a, mp_int *b); |
| 6453 +#else |
| 6454 +#define mp_sqr(a, b) mp_mul(a, a, b) |
| 6455 +#endif |
| 6456 +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r); |
| 6457 +mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r); |
| 6458 +mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c); |
| 6459 +mp_err mp_2expt(mp_int *a, mp_digit k); |
| 6460 +mp_err mp_sqrt(const mp_int *a, mp_int *b); |
| 6461 + |
| 6462 +/* Modular arithmetic */ |
| 6463 +#if MP_MODARITH |
| 6464 +mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c); |
| 6465 +mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c); |
| 6466 +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c); |
| 6467 +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c); |
| 6468 +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c); |
| 6469 +#if MP_SQUARE |
| 6470 +mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c); |
| 6471 +#else |
| 6472 +#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c) |
| 6473 +#endif |
| 6474 +mp_err mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
; |
| 6475 +mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c); |
| 6476 +#endif /* MP_MODARITH */ |
| 6477 + |
| 6478 +/* Comparisons */ |
| 6479 +int mp_cmp_z(const mp_int *a); |
| 6480 +int mp_cmp_d(const mp_int *a, mp_digit d); |
| 6481 +int mp_cmp(const mp_int *a, const mp_int *b); |
| 6482 +int mp_cmp_mag(mp_int *a, mp_int *b); |
| 6483 +int mp_cmp_int(const mp_int *a, long z); |
| 6484 +int mp_isodd(const mp_int *a); |
| 6485 +int mp_iseven(const mp_int *a); |
| 6486 + |
| 6487 +/* Number theoretic */ |
| 6488 +#if MP_NUMTH |
| 6489 +mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c); |
| 6490 +mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c); |
| 6491 +mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *
y); |
| 6492 +mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c); |
| 6493 +mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c); |
| 6494 +#endif /* end MP_NUMTH */ |
| 6495 + |
| 6496 +/* Input and output */ |
| 6497 +#if MP_IOFUNC |
| 6498 +void mp_print(mp_int *mp, FILE *ofp); |
| 6499 +#endif /* end MP_IOFUNC */ |
| 6500 + |
| 6501 +/* Base conversion */ |
| 6502 +mp_err mp_read_raw(mp_int *mp, char *str, int len); |
| 6503 +int mp_raw_size(mp_int *mp); |
| 6504 +mp_err mp_toraw(mp_int *mp, char *str); |
| 6505 +mp_err mp_read_radix(mp_int *mp, const char *str, int radix); |
| 6506 +mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix); |
| 6507 +int mp_radix_size(mp_int *mp, int radix); |
| 6508 +mp_err mp_toradix(mp_int *mp, char *str, int radix); |
| 6509 +int mp_tovalue(char ch, int r); |
| 6510 + |
| 6511 +#define mp_tobinary(M, S) mp_toradix((M), (S), 2) |
| 6512 +#define mp_tooctal(M, S) mp_toradix((M), (S), 8) |
| 6513 +#define mp_todecimal(M, S) mp_toradix((M), (S), 10) |
| 6514 +#define mp_tohex(M, S) mp_toradix((M), (S), 16) |
| 6515 + |
| 6516 +/* Error strings */ |
| 6517 +const char *mp_strerror(mp_err ec); |
| 6518 + |
| 6519 +/* Octet string conversion functions */ |
| 6520 +mp_err mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size le
n); |
| 6521 +int mp_unsigned_octet_size(const mp_int *mp); |
| 6522 +mp_err mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxl
en); |
| 6523 +mp_err mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen
); |
| 6524 +mp_err mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size len); |
| 6525 + |
| 6526 +/* Miscellaneous */ |
| 6527 +mp_size mp_trailing_zeros(const mp_int *mp); |
| 6528 +void freebl_cpuid(unsigned long op, unsigned long *eax, |
| 6529 + unsigned long *ebx, unsigned long *ecx, |
| 6530 + unsigned long *edx); |
| 6531 + |
| 6532 + |
| 6533 +#define MP_CHECKOK(x) if (MP_OKAY > (res = (x))) goto CLEANUP |
| 6534 +#define MP_CHECKERR(x) if (MP_OKAY > (res = (x))) goto CLEANUP |
| 6535 + |
| 6536 +#if defined(MP_API_COMPATIBLE) |
| 6537 +#define NEG MP_NEG |
| 6538 +#define ZPOS MP_ZPOS |
| 6539 +#define DIGIT_MAX MP_DIGIT_MAX |
| 6540 +#define DIGIT_BIT MP_DIGIT_BIT |
| 6541 +#define DIGIT_FMT MP_DIGIT_FMT |
| 6542 +#define RADIX MP_RADIX |
| 6543 +#define MAX_RADIX MP_MAX_RADIX |
| 6544 +#define SIGN(MP) MP_SIGN(MP) |
| 6545 +#define USED(MP) MP_USED(MP) |
| 6546 +#define ALLOC(MP) MP_ALLOC(MP) |
| 6547 +#define DIGITS(MP) MP_DIGITS(MP) |
| 6548 +#define DIGIT(MP,N) MP_DIGIT(MP,N) |
| 6549 + |
| 6550 +#if MP_ARGCHK == 1 |
| 6551 +#define ARGCHK(X,Y) {if(!(X)){return (Y);}} |
| 6552 +#elif MP_ARGCHK == 2 |
| 6553 +#include <assert.h> |
| 6554 +#define ARGCHK(X,Y) assert(X) |
| 6555 +#else |
| 6556 +#define ARGCHK(X,Y) /* */ |
| 6557 +#endif |
| 6558 +#endif /* defined MP_API_COMPATIBLE */ |
| 6559 + |
| 6560 +#endif /* end _H_MPI_ */ |
| 6561 diff --git a/net/third_party/nss/ssl/mpi/mplogic.c b/net/third_party/nss/ssl/mpi
/mplogic.c |
| 6562 new file mode 100644 |
| 6563 index 0000000..216f07a |
| 6564 --- /dev/null |
| 6565 +++ b/net/third_party/nss/ssl/mpi/mplogic.c |
| 6566 @@ -0,0 +1,466 @@ |
| 6567 +/* |
| 6568 + * mplogic.c |
| 6569 + * |
| 6570 + * Bitwise logical operations on MPI values |
| 6571 + * |
| 6572 + * ***** BEGIN LICENSE BLOCK ***** |
| 6573 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 6574 + * |
| 6575 + * The contents of this file are subject to the Mozilla Public License Version |
| 6576 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 6577 + * the License. You may obtain a copy of the License at |
| 6578 + * http://www.mozilla.org/MPL/ |
| 6579 + * |
| 6580 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 6581 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 6582 + * for the specific language governing rights and limitations under the |
| 6583 + * License. |
| 6584 + * |
| 6585 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 6586 + * |
| 6587 + * The Initial Developer of the Original Code is |
| 6588 + * Michael J. Fromberger. |
| 6589 + * Portions created by the Initial Developer are Copyright (C) 1998 |
| 6590 + * the Initial Developer. All Rights Reserved. |
| 6591 + * |
| 6592 + * Contributor(s): |
| 6593 + * |
| 6594 + * Alternatively, the contents of this file may be used under the terms of |
| 6595 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 6596 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 6597 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 6598 + * of those above. If you wish to allow use of your version of this file only |
| 6599 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 6600 + * use your version of this file under the terms of the MPL, indicate your |
| 6601 + * decision by deleting the provisions above and replace them with the notice |
| 6602 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 6603 + * the provisions above, a recipient may use your version of this file under |
| 6604 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 6605 + * |
| 6606 + * ***** END LICENSE BLOCK ***** */ |
| 6607 +/* $Id: mplogic.c,v 1.15 2004/04/27 23:04:36 gerv%gerv.net Exp $ */ |
| 6608 + |
| 6609 +#define MP_API_COMPATIBLE 1 |
| 6610 +#include "mpi-priv.h" |
| 6611 +#include "mplogic.h" |
| 6612 + |
| 6613 +/* {{{ Lookup table for population count */ |
| 6614 + |
| 6615 +static unsigned char bitc[] = { |
| 6616 + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, |
| 6617 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 6618 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 6619 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 6620 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 6621 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 6622 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 6623 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 6624 + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, |
| 6625 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 6626 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 6627 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 6628 + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, |
| 6629 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 6630 + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, |
| 6631 + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 |
| 6632 +}; |
| 6633 + |
| 6634 +/* }}} */ |
| 6635 + |
| 6636 +/*------------------------------------------------------------------------*/ |
| 6637 +/* |
| 6638 + mpl_not(a, b) - compute b = ~a |
| 6639 + mpl_and(a, b, c) - compute c = a & b |
| 6640 + mpl_or(a, b, c) - compute c = a | b |
| 6641 + mpl_xor(a, b, c) - compute c = a ^ b |
| 6642 + */ |
| 6643 + |
| 6644 +/* {{{ mpl_not(a, b) */ |
| 6645 + |
| 6646 +mp_err mpl_not(mp_int *a, mp_int *b) |
| 6647 +{ |
| 6648 + mp_err res; |
| 6649 + unsigned int ix; |
| 6650 + |
| 6651 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 6652 + |
| 6653 + if((res = mp_copy(a, b)) != MP_OKAY) |
| 6654 + return res; |
| 6655 + |
| 6656 + /* This relies on the fact that the digit type is unsigned */ |
| 6657 + for(ix = 0; ix < USED(b); ix++) |
| 6658 + DIGIT(b, ix) = ~DIGIT(b, ix); |
| 6659 + |
| 6660 + s_mp_clamp(b); |
| 6661 + |
| 6662 + return MP_OKAY; |
| 6663 + |
| 6664 +} /* end mpl_not() */ |
| 6665 + |
| 6666 +/* }}} */ |
| 6667 + |
| 6668 +/* {{{ mpl_and(a, b, c) */ |
| 6669 + |
| 6670 +mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c) |
| 6671 +{ |
| 6672 + mp_int *which, *other; |
| 6673 + mp_err res; |
| 6674 + unsigned int ix; |
| 6675 + |
| 6676 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 6677 + |
| 6678 + if(USED(a) <= USED(b)) { |
| 6679 + which = a; |
| 6680 + other = b; |
| 6681 + } else { |
| 6682 + which = b; |
| 6683 + other = a; |
| 6684 + } |
| 6685 + |
| 6686 + if((res = mp_copy(which, c)) != MP_OKAY) |
| 6687 + return res; |
| 6688 + |
| 6689 + for(ix = 0; ix < USED(which); ix++) |
| 6690 + DIGIT(c, ix) &= DIGIT(other, ix); |
| 6691 + |
| 6692 + s_mp_clamp(c); |
| 6693 + |
| 6694 + return MP_OKAY; |
| 6695 + |
| 6696 +} /* end mpl_and() */ |
| 6697 + |
| 6698 +/* }}} */ |
| 6699 + |
| 6700 +/* {{{ mpl_or(a, b, c) */ |
| 6701 + |
| 6702 +mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c) |
| 6703 +{ |
| 6704 + mp_int *which, *other; |
| 6705 + mp_err res; |
| 6706 + unsigned int ix; |
| 6707 + |
| 6708 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 6709 + |
| 6710 + if(USED(a) >= USED(b)) { |
| 6711 + which = a; |
| 6712 + other = b; |
| 6713 + } else { |
| 6714 + which = b; |
| 6715 + other = a; |
| 6716 + } |
| 6717 + |
| 6718 + if((res = mp_copy(which, c)) != MP_OKAY) |
| 6719 + return res; |
| 6720 + |
| 6721 + for(ix = 0; ix < USED(which); ix++) |
| 6722 + DIGIT(c, ix) |= DIGIT(other, ix); |
| 6723 + |
| 6724 + return MP_OKAY; |
| 6725 + |
| 6726 +} /* end mpl_or() */ |
| 6727 + |
| 6728 +/* }}} */ |
| 6729 + |
| 6730 +/* {{{ mpl_xor(a, b, c) */ |
| 6731 + |
| 6732 +mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c) |
| 6733 +{ |
| 6734 + mp_int *which, *other; |
| 6735 + mp_err res; |
| 6736 + unsigned int ix; |
| 6737 + |
| 6738 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 6739 + |
| 6740 + if(USED(a) >= USED(b)) { |
| 6741 + which = a; |
| 6742 + other = b; |
| 6743 + } else { |
| 6744 + which = b; |
| 6745 + other = a; |
| 6746 + } |
| 6747 + |
| 6748 + if((res = mp_copy(which, c)) != MP_OKAY) |
| 6749 + return res; |
| 6750 + |
| 6751 + for(ix = 0; ix < USED(which); ix++) |
| 6752 + DIGIT(c, ix) ^= DIGIT(other, ix); |
| 6753 + |
| 6754 + s_mp_clamp(c); |
| 6755 + |
| 6756 + return MP_OKAY; |
| 6757 + |
| 6758 +} /* end mpl_xor() */ |
| 6759 + |
| 6760 +/* }}} */ |
| 6761 + |
| 6762 +/*------------------------------------------------------------------------*/ |
| 6763 +/* |
| 6764 + mpl_rsh(a, b, d) - b = a >> d |
| 6765 + mpl_lsh(a, b, d) - b = a << d |
| 6766 + */ |
| 6767 + |
| 6768 +/* {{{ mpl_rsh(a, b, d) */ |
| 6769 + |
| 6770 +mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d) |
| 6771 +{ |
| 6772 + mp_err res; |
| 6773 + |
| 6774 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 6775 + |
| 6776 + if((res = mp_copy(a, b)) != MP_OKAY) |
| 6777 + return res; |
| 6778 + |
| 6779 + s_mp_div_2d(b, d); |
| 6780 + |
| 6781 + return MP_OKAY; |
| 6782 + |
| 6783 +} /* end mpl_rsh() */ |
| 6784 + |
| 6785 +/* }}} */ |
| 6786 + |
| 6787 +/* {{{ mpl_lsh(a, b, d) */ |
| 6788 + |
| 6789 +mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d) |
| 6790 +{ |
| 6791 + mp_err res; |
| 6792 + |
| 6793 + ARGCHK(a != NULL && b != NULL, MP_BADARG); |
| 6794 + |
| 6795 + if((res = mp_copy(a, b)) != MP_OKAY) |
| 6796 + return res; |
| 6797 + |
| 6798 + return s_mp_mul_2d(b, d); |
| 6799 + |
| 6800 +} /* end mpl_lsh() */ |
| 6801 + |
| 6802 +/* }}} */ |
| 6803 + |
| 6804 +/*------------------------------------------------------------------------*/ |
| 6805 +/* |
| 6806 + mpl_num_set(a, num) |
| 6807 + |
| 6808 + Count the number of set bits in the binary representation of a. |
| 6809 + Returns MP_OKAY and sets 'num' to be the number of such bits, if |
| 6810 + possible. If num is NULL, the result is thrown away, but it is |
| 6811 + not considered an error. |
| 6812 + |
| 6813 + mpl_num_clear() does basically the same thing for clear bits. |
| 6814 + */ |
| 6815 + |
| 6816 +/* {{{ mpl_num_set(a, num) */ |
| 6817 + |
| 6818 +mp_err mpl_num_set(mp_int *a, int *num) |
| 6819 +{ |
| 6820 + unsigned int ix; |
| 6821 + int db, nset = 0; |
| 6822 + mp_digit cur; |
| 6823 + unsigned char reg; |
| 6824 + |
| 6825 + ARGCHK(a != NULL, MP_BADARG); |
| 6826 + |
| 6827 + for(ix = 0; ix < USED(a); ix++) { |
| 6828 + cur = DIGIT(a, ix); |
| 6829 + |
| 6830 + for(db = 0; db < sizeof(mp_digit); db++) { |
| 6831 + reg = (unsigned char)(cur >> (CHAR_BIT * db)); |
| 6832 + |
| 6833 + nset += bitc[reg]; |
| 6834 + } |
| 6835 + } |
| 6836 + |
| 6837 + if(num) |
| 6838 + *num = nset; |
| 6839 + |
| 6840 + return MP_OKAY; |
| 6841 + |
| 6842 +} /* end mpl_num_set() */ |
| 6843 + |
| 6844 +/* }}} */ |
| 6845 + |
| 6846 +/* {{{ mpl_num_clear(a, num) */ |
| 6847 + |
| 6848 +mp_err mpl_num_clear(mp_int *a, int *num) |
| 6849 +{ |
| 6850 + unsigned int ix; |
| 6851 + int db, nset = 0; |
| 6852 + mp_digit cur; |
| 6853 + unsigned char reg; |
| 6854 + |
| 6855 + ARGCHK(a != NULL, MP_BADARG); |
| 6856 + |
| 6857 + for(ix = 0; ix < USED(a); ix++) { |
| 6858 + cur = DIGIT(a, ix); |
| 6859 + |
| 6860 + for(db = 0; db < sizeof(mp_digit); db++) { |
| 6861 + reg = (unsigned char)(cur >> (CHAR_BIT * db)); |
| 6862 + |
| 6863 + nset += bitc[UCHAR_MAX - reg]; |
| 6864 + } |
| 6865 + } |
| 6866 + |
| 6867 + if(num) |
| 6868 + *num = nset; |
| 6869 + |
| 6870 + return MP_OKAY; |
| 6871 + |
| 6872 + |
| 6873 +} /* end mpl_num_clear() */ |
| 6874 + |
| 6875 +/* }}} */ |
| 6876 + |
| 6877 +/*------------------------------------------------------------------------*/ |
| 6878 +/* |
| 6879 + mpl_parity(a) |
| 6880 + |
| 6881 + Determines the bitwise parity of the value given. Returns MP_EVEN |
| 6882 + if an even number of digits are set, MP_ODD if an odd number are |
| 6883 + set. |
| 6884 + */ |
| 6885 + |
| 6886 +/* {{{ mpl_parity(a) */ |
| 6887 + |
| 6888 +mp_err mpl_parity(mp_int *a) |
| 6889 +{ |
| 6890 + unsigned int ix; |
| 6891 + int par = 0; |
| 6892 + mp_digit cur; |
| 6893 + |
| 6894 + ARGCHK(a != NULL, MP_BADARG); |
| 6895 + |
| 6896 + for(ix = 0; ix < USED(a); ix++) { |
| 6897 + int shft = (sizeof(mp_digit) * CHAR_BIT) / 2; |
| 6898 + |
| 6899 + cur = DIGIT(a, ix); |
| 6900 + |
| 6901 + /* Compute parity for current digit */ |
| 6902 + while(shft != 0) { |
| 6903 + cur ^= (cur >> shft); |
| 6904 + shft >>= 1; |
| 6905 + } |
| 6906 + cur &= 1; |
| 6907 + |
| 6908 + /* XOR with running parity so far */ |
| 6909 + par ^= cur; |
| 6910 + } |
| 6911 + |
| 6912 + if(par) |
| 6913 + return MP_ODD; |
| 6914 + else |
| 6915 + return MP_EVEN; |
| 6916 + |
| 6917 +} /* end mpl_parity() */ |
| 6918 + |
| 6919 +/* }}} */ |
| 6920 + |
| 6921 +/* |
| 6922 + mpl_set_bit |
| 6923 + |
| 6924 + Returns MP_OKAY or some error code. |
| 6925 + Grows a if needed to set a bit to 1. |
| 6926 + */ |
| 6927 +mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value) |
| 6928 +{ |
| 6929 + mp_size ix; |
| 6930 + mp_err rv; |
| 6931 + mp_digit mask; |
| 6932 + |
| 6933 + ARGCHK(a != NULL, MP_BADARG); |
| 6934 + |
| 6935 + ix = bitNum / MP_DIGIT_BIT; |
| 6936 + if (ix + 1 > MP_USED(a)) { |
| 6937 + rv = s_mp_pad(a, ix + 1); |
| 6938 + if (rv != MP_OKAY) |
| 6939 + return rv; |
| 6940 + } |
| 6941 + |
| 6942 + bitNum = bitNum % MP_DIGIT_BIT; |
| 6943 + mask = (mp_digit)1 << bitNum; |
| 6944 + if (value) |
| 6945 + MP_DIGIT(a,ix) |= mask; |
| 6946 + else |
| 6947 + MP_DIGIT(a,ix) &= ~mask; |
| 6948 + s_mp_clamp(a); |
| 6949 + return MP_OKAY; |
| 6950 +} |
| 6951 + |
| 6952 +/* |
| 6953 + mpl_get_bit |
| 6954 + |
| 6955 + returns 0 or 1 or some (negative) error code. |
| 6956 + */ |
| 6957 +mp_err mpl_get_bit(const mp_int *a, mp_size bitNum) |
| 6958 +{ |
| 6959 + mp_size bit, ix; |
| 6960 + mp_err rv; |
| 6961 + |
| 6962 + ARGCHK(a != NULL, MP_BADARG); |
| 6963 + |
| 6964 + ix = bitNum / MP_DIGIT_BIT; |
| 6965 + ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE); |
| 6966 + |
| 6967 + bit = bitNum % MP_DIGIT_BIT; |
| 6968 + rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1; |
| 6969 + return rv; |
| 6970 +} |
| 6971 + |
| 6972 +/* |
| 6973 + mpl_get_bits |
| 6974 + - Extracts numBits bits from a, where the least significant extracted bit |
| 6975 + is bit lsbNum. Returns a negative value if error occurs. |
| 6976 + - Because sign bit is used to indicate error, maximum number of bits to |
| 6977 + be returned is the lesser of (a) the number of bits in an mp_digit, or |
| 6978 + (b) one less than the number of bits in an mp_err. |
| 6979 + - lsbNum + numbits can be greater than the number of significant bits in |
| 6980 + integer a, as long as bit lsbNum is in the high order digit of a. |
| 6981 + */ |
| 6982 +mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits) |
| 6983 +{ |
| 6984 + mp_size rshift = (lsbNum % MP_DIGIT_BIT); |
| 6985 + mp_size lsWndx = (lsbNum / MP_DIGIT_BIT); |
| 6986 + mp_digit * digit = MP_DIGITS(a) + lsWndx; |
| 6987 + mp_digit mask = ((1 << numBits) - 1); |
| 6988 + |
| 6989 + ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG); |
| 6990 + ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE); |
| 6991 + |
| 6992 + if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) || |
| 6993 + (lsWndx + 1 >= MP_USED(a))) { |
| 6994 + mask &= (digit[0] >> rshift); |
| 6995 + } else { |
| 6996 + mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift))); |
| 6997 + } |
| 6998 + return (mp_err)mask; |
| 6999 +} |
| 7000 + |
| 7001 +/* |
| 7002 + mpl_significant_bits |
| 7003 + returns number of significnant bits in abs(a). |
| 7004 + returns 1 if value is zero. |
| 7005 + */ |
| 7006 +mp_err mpl_significant_bits(const mp_int *a) |
| 7007 +{ |
| 7008 + mp_err bits = 0; |
| 7009 + int ix; |
| 7010 + |
| 7011 + ARGCHK(a != NULL, MP_BADARG); |
| 7012 + |
| 7013 + ix = MP_USED(a); |
| 7014 + for (ix = MP_USED(a); ix > 0; ) { |
| 7015 + mp_digit d; |
| 7016 + d = MP_DIGIT(a, --ix); |
| 7017 + if (d) { |
| 7018 + while (d) { |
| 7019 + ++bits; |
| 7020 + d >>= 1; |
| 7021 + } |
| 7022 + break; |
| 7023 + } |
| 7024 + } |
| 7025 + bits += ix * MP_DIGIT_BIT; |
| 7026 + if (!bits) |
| 7027 + bits = 1; |
| 7028 + return bits; |
| 7029 +} |
| 7030 + |
| 7031 +/*------------------------------------------------------------------------*/ |
| 7032 +/* HERE THERE BE DRAGONS */ |
| 7033 diff --git a/net/third_party/nss/ssl/mpi/mplogic.h b/net/third_party/nss/ssl/mpi
/mplogic.h |
| 7034 new file mode 100644 |
| 7035 index 0000000..de831dc |
| 7036 --- /dev/null |
| 7037 +++ b/net/third_party/nss/ssl/mpi/mplogic.h |
| 7038 @@ -0,0 +1,85 @@ |
| 7039 +/* |
| 7040 + * mplogic.h |
| 7041 + * |
| 7042 + * Bitwise logical operations on MPI values |
| 7043 + * |
| 7044 + * ***** BEGIN LICENSE BLOCK ***** |
| 7045 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 7046 + * |
| 7047 + * The contents of this file are subject to the Mozilla Public License Version |
| 7048 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 7049 + * the License. You may obtain a copy of the License at |
| 7050 + * http://www.mozilla.org/MPL/ |
| 7051 + * |
| 7052 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 7053 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 7054 + * for the specific language governing rights and limitations under the |
| 7055 + * License. |
| 7056 + * |
| 7057 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 7058 + * |
| 7059 + * The Initial Developer of the Original Code is |
| 7060 + * Michael J. Fromberger. |
| 7061 + * Portions created by the Initial Developer are Copyright (C) 1998 |
| 7062 + * the Initial Developer. All Rights Reserved. |
| 7063 + * |
| 7064 + * Contributor(s): |
| 7065 + * |
| 7066 + * Alternatively, the contents of this file may be used under the terms of |
| 7067 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 7068 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 7069 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 7070 + * of those above. If you wish to allow use of your version of this file only |
| 7071 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 7072 + * use your version of this file under the terms of the MPL, indicate your |
| 7073 + * decision by deleting the provisions above and replace them with the notice |
| 7074 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 7075 + * the provisions above, a recipient may use your version of this file under |
| 7076 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 7077 + * |
| 7078 + * ***** END LICENSE BLOCK ***** */ |
| 7079 +/* $Id: mplogic.h,v 1.7 2004/04/27 23:04:36 gerv%gerv.net Exp $ */ |
| 7080 + |
| 7081 +#ifndef _H_MPLOGIC_ |
| 7082 +#define _H_MPLOGIC_ |
| 7083 + |
| 7084 +#include "mpi.h" |
| 7085 + |
| 7086 +/* |
| 7087 + The logical operations treat an mp_int as if it were a bit vector, |
| 7088 + without regard to its sign (an mp_int is represented in a signed |
| 7089 + magnitude format). Values are treated as if they had an infinite |
| 7090 + string of zeros left of the most-significant bit. |
| 7091 + */ |
| 7092 + |
| 7093 +/* Parity results */ |
| 7094 + |
| 7095 +#define MP_EVEN MP_YES |
| 7096 +#define MP_ODD MP_NO |
| 7097 + |
| 7098 +/* Bitwise functions */ |
| 7099 + |
| 7100 +mp_err mpl_not(mp_int *a, mp_int *b); /* one's complement */ |
| 7101 +mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c); /* bitwise AND */ |
| 7102 +mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c); /* bitwise OR */ |
| 7103 +mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c); /* bitwise XOR */ |
| 7104 + |
| 7105 +/* Shift functions */ |
| 7106 + |
| 7107 +mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d); /* right shift */ |
| 7108 +mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d); /* left shift */ |
| 7109 + |
| 7110 +/* Bit count and parity */ |
| 7111 + |
| 7112 +mp_err mpl_num_set(mp_int *a, int *num); /* count set bits */ |
| 7113 +mp_err mpl_num_clear(mp_int *a, int *num); /* count clear bits */ |
| 7114 +mp_err mpl_parity(mp_int *a); /* determine parity */ |
| 7115 + |
| 7116 +/* Get & Set the value of a bit */ |
| 7117 + |
| 7118 +mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value); |
| 7119 +mp_err mpl_get_bit(const mp_int *a, mp_size bitNum); |
| 7120 +mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits); |
| 7121 +mp_err mpl_significant_bits(const mp_int *a); |
| 7122 + |
| 7123 +#endif /* end _H_MPLOGIC_ */ |
| 7124 diff --git a/net/third_party/nss/ssl/mpi/mpmontg.c b/net/third_party/nss/ssl/mpi
/mpmontg.c |
| 7125 new file mode 100644 |
| 7126 index 0000000..088b7eb |
| 7127 --- /dev/null |
| 7128 +++ b/net/third_party/nss/ssl/mpi/mpmontg.c |
| 7129 @@ -0,0 +1,1210 @@ |
| 7130 +/* ***** BEGIN LICENSE BLOCK ***** |
| 7131 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 7132 + * |
| 7133 + * The contents of this file are subject to the Mozilla Public License Version |
| 7134 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 7135 + * the License. You may obtain a copy of the License at |
| 7136 + * http://www.mozilla.org/MPL/ |
| 7137 + * |
| 7138 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 7139 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 7140 + * for the specific language governing rights and limitations under the |
| 7141 + * License. |
| 7142 + * |
| 7143 + * The Original Code is the Netscape security libraries. |
| 7144 + * |
| 7145 + * The Initial Developer of the Original Code is |
| 7146 + * Netscape Communications Corporation. |
| 7147 + * Portions created by the Initial Developer are Copyright (C) 2000 |
| 7148 + * the Initial Developer. All Rights Reserved. |
| 7149 + * |
| 7150 + * Contributor(s): |
| 7151 + * Sheueling Chang Shantz <sheueling.chang@sun.com>, |
| 7152 + * Stephen Fung <stephen.fung@sun.com>, and |
| 7153 + * Douglas Stebila <douglas@stebila.ca> of Sun Laboratories. |
| 7154 + * |
| 7155 + * Alternatively, the contents of this file may be used under the terms of |
| 7156 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 7157 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 7158 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 7159 + * of those above. If you wish to allow use of your version of this file only |
| 7160 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 7161 + * use your version of this file under the terms of the MPL, indicate your |
| 7162 + * decision by deleting the provisions above and replace them with the notice |
| 7163 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 7164 + * the provisions above, a recipient may use your version of this file under |
| 7165 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 7166 + * |
| 7167 + * ***** END LICENSE BLOCK ***** */ |
| 7168 +/* $Id: mpmontg.c,v 1.22 2010/05/02 22:36:41 nelson%bolyard.com Exp $ */ |
| 7169 + |
| 7170 +/* This file implements moduluar exponentiation using Montgomery's |
| 7171 + * method for modular reduction. This file implements the method |
| 7172 + * described as "Improvement 1" in the paper "A Cryptogrpahic Library for |
| 7173 + * the Motorola DSP56000" by Stephen R. Dusse' and Burton S. Kaliski Jr. |
| 7174 + * published in "Advances in Cryptology: Proceedings of EUROCRYPT '90" |
| 7175 + * "Lecture Notes in Computer Science" volume 473, 1991, pg 230-244, |
| 7176 + * published by Springer Verlag. |
| 7177 + */ |
| 7178 + |
| 7179 +#define MP_API_COMPATIBLE 1 |
| 7180 +#define MP_USING_CACHE_SAFE_MOD_EXP 1 |
| 7181 +#include <string.h> |
| 7182 +#include "mpi-priv.h" |
| 7183 +#include "mplogic.h" |
| 7184 +#include "mpprime.h" |
| 7185 +#ifdef MP_USING_MONT_MULF |
| 7186 +#include "montmulf.h" |
| 7187 +#endif |
| 7188 +#include <stddef.h> /* ptrdiff_t */ |
| 7189 + |
| 7190 +/* if MP_CHAR_STORE_SLOW is defined, we */ |
| 7191 +/* need to know endianness of this platform. */ |
| 7192 +#ifdef MP_CHAR_STORE_SLOW |
| 7193 +#if !defined(MP_IS_BIG_ENDIAN) && !defined(MP_IS_LITTLE_ENDIAN) |
| 7194 +#error "You must define MP_IS_BIG_ENDIAN or MP_IS_LITTLE_ENDIAN\n" \ |
| 7195 + " if you define MP_CHAR_STORE_SLOW." |
| 7196 +#endif |
| 7197 +#endif |
| 7198 + |
| 7199 +#define STATIC |
| 7200 + |
| 7201 +#define MAX_ODD_INTS 32 /* 2 ** (WINDOW_BITS - 1) */ |
| 7202 + |
| 7203 +#if defined(_WIN32_WCE) |
| 7204 +#define ABORT res = MP_UNDEF; goto CLEANUP |
| 7205 +#else |
| 7206 +#define ABORT abort() |
| 7207 +#endif |
| 7208 + |
| 7209 +/* computes T = REDC(T), 2^b == R */ |
| 7210 +mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm) |
| 7211 +{ |
| 7212 + mp_err res; |
| 7213 + mp_size i; |
| 7214 + |
| 7215 + i = MP_USED(T) + MP_USED(&mmm->N) + 2; |
| 7216 + MP_CHECKOK( s_mp_pad(T, i) ); |
| 7217 + for (i = 0; i < MP_USED(&mmm->N); ++i ) { |
| 7218 + mp_digit m_i = MP_DIGIT(T, i) * mmm->n0prime; |
| 7219 + /* T += N * m_i * (MP_RADIX ** i); */ |
| 7220 + MP_CHECKOK( s_mp_mul_d_add_offset(&mmm->N, m_i, T, i) ); |
| 7221 + } |
| 7222 + s_mp_clamp(T); |
| 7223 + |
| 7224 + /* T /= R */ |
| 7225 + s_mp_div_2d(T, mmm->b); |
| 7226 + |
| 7227 + if ((res = s_mp_cmp(T, &mmm->N)) >= 0) { |
| 7228 + /* T = T - N */ |
| 7229 + MP_CHECKOK( s_mp_sub(T, &mmm->N) ); |
| 7230 +#ifdef DEBUG |
| 7231 + if ((res = mp_cmp(T, &mmm->N)) >= 0) { |
| 7232 + res = MP_UNDEF; |
| 7233 + goto CLEANUP; |
| 7234 + } |
| 7235 +#endif |
| 7236 + } |
| 7237 + res = MP_OKAY; |
| 7238 +CLEANUP: |
| 7239 + return res; |
| 7240 +} |
| 7241 + |
| 7242 +#if !defined(MP_ASSEMBLY_MUL_MONT) && !defined(MP_MONT_USE_MP_MUL) |
| 7243 +mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c, |
| 7244 + mp_mont_modulus *mmm) |
| 7245 +{ |
| 7246 + mp_digit *pb; |
| 7247 + mp_digit m_i; |
| 7248 + mp_err res; |
| 7249 + mp_size ib; |
| 7250 + mp_size useda, usedb; |
| 7251 + |
| 7252 + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); |
| 7253 + |
| 7254 + if (MP_USED(a) < MP_USED(b)) { |
| 7255 + const mp_int *xch = b; /* switch a and b, to do fewer outer loops */ |
| 7256 + b = a; |
| 7257 + a = xch; |
| 7258 + } |
| 7259 + |
| 7260 + MP_USED(c) = 1; MP_DIGIT(c, 0) = 0; |
| 7261 + ib = MP_USED(a) + MP_MAX(MP_USED(b), MP_USED(&mmm->N)) + 2; |
| 7262 + if((res = s_mp_pad(c, ib)) != MP_OKAY) |
| 7263 + goto CLEANUP; |
| 7264 + |
| 7265 + useda = MP_USED(a); |
| 7266 + pb = MP_DIGITS(b); |
| 7267 + s_mpv_mul_d(MP_DIGITS(a), useda, *pb++, MP_DIGITS(c)); |
| 7268 + s_mp_setz(MP_DIGITS(c) + useda + 1, ib - (useda + 1)); |
| 7269 + m_i = MP_DIGIT(c, 0) * mmm->n0prime; |
| 7270 + s_mp_mul_d_add_offset(&mmm->N, m_i, c, 0); |
| 7271 + |
| 7272 + /* Outer loop: Digits of b */ |
| 7273 + usedb = MP_USED(b); |
| 7274 + for (ib = 1; ib < usedb; ib++) { |
| 7275 + mp_digit b_i = *pb++; |
| 7276 + |
| 7277 + /* Inner product: Digits of a */ |
| 7278 + if (b_i) |
| 7279 + s_mpv_mul_d_add_prop(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib); |
| 7280 + m_i = MP_DIGIT(c, ib) * mmm->n0prime; |
| 7281 + s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib); |
| 7282 + } |
| 7283 + if (usedb < MP_USED(&mmm->N)) { |
| 7284 + for (usedb = MP_USED(&mmm->N); ib < usedb; ++ib ) { |
| 7285 + m_i = MP_DIGIT(c, ib) * mmm->n0prime; |
| 7286 + s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib); |
| 7287 + } |
| 7288 + } |
| 7289 + s_mp_clamp(c); |
| 7290 + s_mp_div_2d(c, mmm->b); |
| 7291 + if (s_mp_cmp(c, &mmm->N) >= 0) { |
| 7292 + MP_CHECKOK( s_mp_sub(c, &mmm->N) ); |
| 7293 + } |
| 7294 + res = MP_OKAY; |
| 7295 + |
| 7296 +CLEANUP: |
| 7297 + return res; |
| 7298 +} |
| 7299 +#endif |
| 7300 + |
| 7301 +STATIC |
| 7302 +mp_err s_mp_to_mont(const mp_int *x, mp_mont_modulus *mmm, mp_int *xMont) |
| 7303 +{ |
| 7304 + mp_err res; |
| 7305 + |
| 7306 + /* xMont = x * R mod N where N is modulus */ |
| 7307 + MP_CHECKOK( mpl_lsh(x, xMont, mmm->b) ); /* xMont = x << b */ |
| 7308 + MP_CHECKOK( mp_div(xMont, &mmm->N, 0, xMont) ); /* mod N */ |
| 7309 +CLEANUP: |
| 7310 + return res; |
| 7311 +} |
| 7312 + |
| 7313 +#ifdef MP_USING_MONT_MULF |
| 7314 + |
| 7315 +/* the floating point multiply is already cache safe, |
| 7316 + * don't turn on cache safe unless we specifically |
| 7317 + * force it */ |
| 7318 +#ifndef MP_FORCE_CACHE_SAFE |
| 7319 +#undef MP_USING_CACHE_SAFE_MOD_EXP |
| 7320 +#endif |
| 7321 + |
| 7322 +unsigned int mp_using_mont_mulf = 1; |
| 7323 + |
| 7324 +/* computes montgomery square of the integer in mResult */ |
| 7325 +#define SQR \ |
| 7326 + conv_i32_to_d32_and_d16(dm1, d16Tmp, mResult, nLen); \ |
| 7327 + mont_mulf_noconv(mResult, dm1, d16Tmp, \ |
| 7328 + dTmp, dn, MP_DIGITS(modulus), nLen, dn0) |
| 7329 + |
| 7330 +/* computes montgomery product of x and the integer in mResult */ |
| 7331 +#define MUL(x) \ |
| 7332 + conv_i32_to_d32(dm1, mResult, nLen); \ |
| 7333 + mont_mulf_noconv(mResult, dm1, oddPowers[x], \ |
| 7334 + dTmp, dn, MP_DIGITS(modulus), nLen, dn0) |
| 7335 + |
| 7336 +/* Do modular exponentiation using floating point multiply code. */ |
| 7337 +mp_err mp_exptmod_f(const mp_int * montBase, |
| 7338 + const mp_int * exponent, |
| 7339 + const mp_int * modulus, |
| 7340 + mp_int * result, |
| 7341 + mp_mont_modulus *mmm, |
| 7342 + int nLen, |
| 7343 + mp_size bits_in_exponent, |
| 7344 + mp_size window_bits, |
| 7345 + mp_size odd_ints) |
| 7346 +{ |
| 7347 + mp_digit *mResult; |
| 7348 + double *dBuf = 0, *dm1, *dn, *dSqr, *d16Tmp, *dTmp; |
| 7349 + double dn0; |
| 7350 + mp_size i; |
| 7351 + mp_err res; |
| 7352 + int expOff; |
| 7353 + int dSize = 0, oddPowSize, dTmpSize; |
| 7354 + mp_int accum1; |
| 7355 + double *oddPowers[MAX_ODD_INTS]; |
| 7356 + |
| 7357 + /* function for computing n0prime only works if n0 is odd */ |
| 7358 + |
| 7359 + MP_DIGITS(&accum1) = 0; |
| 7360 + |
| 7361 + for (i = 0; i < MAX_ODD_INTS; ++i) |
| 7362 + oddPowers[i] = 0; |
| 7363 + |
| 7364 + MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); |
| 7365 + |
| 7366 + mp_set(&accum1, 1); |
| 7367 + MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); |
| 7368 + MP_CHECKOK( s_mp_pad(&accum1, nLen) ); |
| 7369 + |
| 7370 + oddPowSize = 2 * nLen + 1; |
| 7371 + dTmpSize = 2 * oddPowSize; |
| 7372 + dSize = sizeof(double) * (nLen * 4 + 1 + |
| 7373 + ((odd_ints + 1) * oddPowSize) + dTmpSize); |
| 7374 + dBuf = (double *)malloc(dSize); |
| 7375 + dm1 = dBuf; /* array of d32 */ |
| 7376 + dn = dBuf + nLen; /* array of d32 */ |
| 7377 + dSqr = dn + nLen; /* array of d32 */ |
| 7378 + d16Tmp = dSqr + nLen; /* array of d16 */ |
| 7379 + dTmp = d16Tmp + oddPowSize; |
| 7380 + |
| 7381 + for (i = 0; i < odd_ints; ++i) { |
| 7382 + oddPowers[i] = dTmp; |
| 7383 + dTmp += oddPowSize; |
| 7384 + } |
| 7385 + mResult = (mp_digit *)(dTmp + dTmpSize); /* size is nLen + 1 */ |
| 7386 + |
| 7387 + /* Make dn and dn0 */ |
| 7388 + conv_i32_to_d32(dn, MP_DIGITS(modulus), nLen); |
| 7389 + dn0 = (double)(mmm->n0prime & 0xffff); |
| 7390 + |
| 7391 + /* Make dSqr */ |
| 7392 + conv_i32_to_d32_and_d16(dm1, oddPowers[0], MP_DIGITS(montBase), nLen); |
| 7393 + mont_mulf_noconv(mResult, dm1, oddPowers[0], |
| 7394 + dTmp, dn, MP_DIGITS(modulus), nLen, dn0); |
| 7395 + conv_i32_to_d32(dSqr, mResult, nLen); |
| 7396 + |
| 7397 + for (i = 1; i < odd_ints; ++i) { |
| 7398 + mont_mulf_noconv(mResult, dSqr, oddPowers[i - 1], |
| 7399 + dTmp, dn, MP_DIGITS(modulus), nLen, dn0); |
| 7400 + conv_i32_to_d16(oddPowers[i], mResult, nLen); |
| 7401 + } |
| 7402 + |
| 7403 + s_mp_copy(MP_DIGITS(&accum1), mResult, nLen); /* from, to, len */ |
| 7404 + |
| 7405 + for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_b
its) { |
| 7406 + mp_size smallExp; |
| 7407 + MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); |
| 7408 + smallExp = (mp_size)res; |
| 7409 + |
| 7410 + if (window_bits == 1) { |
| 7411 + if (!smallExp) { |
| 7412 + SQR; |
| 7413 + } else if (smallExp & 1) { |
| 7414 + SQR; MUL(0); |
| 7415 + } else { |
| 7416 + ABORT; |
| 7417 + } |
| 7418 + } else if (window_bits == 4) { |
| 7419 + if (!smallExp) { |
| 7420 + SQR; SQR; SQR; SQR; |
| 7421 + } else if (smallExp & 1) { |
| 7422 + SQR; SQR; SQR; SQR; MUL(smallExp/2); |
| 7423 + } else if (smallExp & 2) { |
| 7424 + SQR; SQR; SQR; MUL(smallExp/4); SQR; |
| 7425 + } else if (smallExp & 4) { |
| 7426 + SQR; SQR; MUL(smallExp/8); SQR; SQR; |
| 7427 + } else if (smallExp & 8) { |
| 7428 + SQR; MUL(smallExp/16); SQR; SQR; SQR; |
| 7429 + } else { |
| 7430 + ABORT; |
| 7431 + } |
| 7432 + } else if (window_bits == 5) { |
| 7433 + if (!smallExp) { |
| 7434 + SQR; SQR; SQR; SQR; SQR; |
| 7435 + } else if (smallExp & 1) { |
| 7436 + SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2); |
| 7437 + } else if (smallExp & 2) { |
| 7438 + SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR; |
| 7439 + } else if (smallExp & 4) { |
| 7440 + SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR; |
| 7441 + } else if (smallExp & 8) { |
| 7442 + SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR; |
| 7443 + } else if (smallExp & 0x10) { |
| 7444 + SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR; |
| 7445 + } else { |
| 7446 + ABORT; |
| 7447 + } |
| 7448 + } else if (window_bits == 6) { |
| 7449 + if (!smallExp) { |
| 7450 + SQR; SQR; SQR; SQR; SQR; SQR; |
| 7451 + } else if (smallExp & 1) { |
| 7452 + SQR; SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2); |
| 7453 + } else if (smallExp & 2) { |
| 7454 + SQR; SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR; |
| 7455 + } else if (smallExp & 4) { |
| 7456 + SQR; SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR; |
| 7457 + } else if (smallExp & 8) { |
| 7458 + SQR; SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR; |
| 7459 + } else if (smallExp & 0x10) { |
| 7460 + SQR; SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR; |
| 7461 + } else if (smallExp & 0x20) { |
| 7462 + SQR; MUL(smallExp/64); SQR; SQR; SQR; SQR; SQR; |
| 7463 + } else { |
| 7464 + ABORT; |
| 7465 + } |
| 7466 + } else { |
| 7467 + ABORT; |
| 7468 + } |
| 7469 + } |
| 7470 + |
| 7471 + s_mp_copy(mResult, MP_DIGITS(&accum1), nLen); /* from, to, len */ |
| 7472 + |
| 7473 + res = s_mp_redc(&accum1, mmm); |
| 7474 + mp_exch(&accum1, result); |
| 7475 + |
| 7476 +CLEANUP: |
| 7477 + mp_clear(&accum1); |
| 7478 + if (dBuf) { |
| 7479 + if (dSize) |
| 7480 + memset(dBuf, 0, dSize); |
| 7481 + free(dBuf); |
| 7482 + } |
| 7483 + |
| 7484 + return res; |
| 7485 +} |
| 7486 +#undef SQR |
| 7487 +#undef MUL |
| 7488 +#endif |
| 7489 + |
| 7490 +#define SQR(a,b) \ |
| 7491 + MP_CHECKOK( mp_sqr(a, b) );\ |
| 7492 + MP_CHECKOK( s_mp_redc(b, mmm) ) |
| 7493 + |
| 7494 +#if defined(MP_MONT_USE_MP_MUL) |
| 7495 +#define MUL(x,a,b) \ |
| 7496 + MP_CHECKOK( mp_mul(a, oddPowers + (x), b) ); \ |
| 7497 + MP_CHECKOK( s_mp_redc(b, mmm) ) |
| 7498 +#else |
| 7499 +#define MUL(x,a,b) \ |
| 7500 + MP_CHECKOK( s_mp_mul_mont(a, oddPowers + (x), b, mmm) ) |
| 7501 +#endif |
| 7502 + |
| 7503 +#define SWAPPA ptmp = pa1; pa1 = pa2; pa2 = ptmp |
| 7504 + |
| 7505 +/* Do modular exponentiation using integer multiply code. */ |
| 7506 +mp_err mp_exptmod_i(const mp_int * montBase, |
| 7507 + const mp_int * exponent, |
| 7508 + const mp_int * modulus, |
| 7509 + mp_int * result, |
| 7510 + mp_mont_modulus *mmm, |
| 7511 + int nLen, |
| 7512 + mp_size bits_in_exponent, |
| 7513 + mp_size window_bits, |
| 7514 + mp_size odd_ints) |
| 7515 +{ |
| 7516 + mp_int *pa1, *pa2, *ptmp; |
| 7517 + mp_size i; |
| 7518 + mp_err res; |
| 7519 + int expOff; |
| 7520 + mp_int accum1, accum2, power2, oddPowers[MAX_ODD_INTS]; |
| 7521 + |
| 7522 + /* power2 = base ** 2; oddPowers[i] = base ** (2*i + 1); */ |
| 7523 + /* oddPowers[i] = base ** (2*i + 1); */ |
| 7524 + |
| 7525 + MP_DIGITS(&accum1) = 0; |
| 7526 + MP_DIGITS(&accum2) = 0; |
| 7527 + MP_DIGITS(&power2) = 0; |
| 7528 + for (i = 0; i < MAX_ODD_INTS; ++i) { |
| 7529 + MP_DIGITS(oddPowers + i) = 0; |
| 7530 + } |
| 7531 + |
| 7532 + MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); |
| 7533 + MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) ); |
| 7534 + |
| 7535 + MP_CHECKOK( mp_init_copy(&oddPowers[0], montBase) ); |
| 7536 + |
| 7537 + mp_init_size(&power2, nLen + 2 * MP_USED(montBase) + 2); |
| 7538 + MP_CHECKOK( mp_sqr(montBase, &power2) ); /* power2 = montBase ** 2 */ |
| 7539 + MP_CHECKOK( s_mp_redc(&power2, mmm) ); |
| 7540 + |
| 7541 + for (i = 1; i < odd_ints; ++i) { |
| 7542 + mp_init_size(oddPowers + i, nLen + 2 * MP_USED(&power2) + 2); |
| 7543 + MP_CHECKOK( mp_mul(oddPowers + (i - 1), &power2, oddPowers + i) ); |
| 7544 + MP_CHECKOK( s_mp_redc(oddPowers + i, mmm) ); |
| 7545 + } |
| 7546 + |
| 7547 + /* set accumulator to montgomery residue of 1 */ |
| 7548 + mp_set(&accum1, 1); |
| 7549 + MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); |
| 7550 + pa1 = &accum1; |
| 7551 + pa2 = &accum2; |
| 7552 + |
| 7553 + for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_b
its) { |
| 7554 + mp_size smallExp; |
| 7555 + MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); |
| 7556 + smallExp = (mp_size)res; |
| 7557 + |
| 7558 + if (window_bits == 1) { |
| 7559 + if (!smallExp) { |
| 7560 + SQR(pa1,pa2); SWAPPA; |
| 7561 + } else if (smallExp & 1) { |
| 7562 + SQR(pa1,pa2); MUL(0,pa2,pa1); |
| 7563 + } else { |
| 7564 + ABORT; |
| 7565 + } |
| 7566 + } else if (window_bits == 4) { |
| 7567 + if (!smallExp) { |
| 7568 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7569 + } else if (smallExp & 1) { |
| 7570 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7571 + MUL(smallExp/2, pa1,pa2); SWAPPA; |
| 7572 + } else if (smallExp & 2) { |
| 7573 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); |
| 7574 + MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA; |
| 7575 + } else if (smallExp & 4) { |
| 7576 + SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/8,pa1,pa2); |
| 7577 + SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; |
| 7578 + } else if (smallExp & 8) { |
| 7579 + SQR(pa1,pa2); MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); |
| 7580 + SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; |
| 7581 + } else { |
| 7582 + ABORT; |
| 7583 + } |
| 7584 + } else if (window_bits == 5) { |
| 7585 + if (!smallExp) { |
| 7586 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7587 + SQR(pa1,pa2); SWAPPA; |
| 7588 + } else if (smallExp & 1) { |
| 7589 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7590 + SQR(pa1,pa2); MUL(smallExp/2,pa2,pa1); |
| 7591 + } else if (smallExp & 2) { |
| 7592 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7593 + MUL(smallExp/4,pa1,pa2); SQR(pa2,pa1); |
| 7594 + } else if (smallExp & 4) { |
| 7595 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); |
| 7596 + MUL(smallExp/8,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7597 + } else if (smallExp & 8) { |
| 7598 + SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/16,pa1,pa2); |
| 7599 + SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7600 + } else if (smallExp & 0x10) { |
| 7601 + SQR(pa1,pa2); MUL(smallExp/32,pa2,pa1); SQR(pa1,pa2); |
| 7602 + SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7603 + } else { |
| 7604 + ABORT; |
| 7605 + } |
| 7606 + } else if (window_bits == 6) { |
| 7607 + if (!smallExp) { |
| 7608 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7609 + SQR(pa1,pa2); SQR(pa2,pa1); |
| 7610 + } else if (smallExp & 1) { |
| 7611 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7612 + SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/2,pa1,pa2); SWAPPA; |
| 7613 + } else if (smallExp & 2) { |
| 7614 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7615 + SQR(pa1,pa2); MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA; |
| 7616 + } else if (smallExp & 4) { |
| 7617 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7618 + MUL(smallExp/8,pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; |
| 7619 + } else if (smallExp & 8) { |
| 7620 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); |
| 7621 + MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 7622 + SQR(pa1,pa2); SWAPPA; |
| 7623 + } else if (smallExp & 0x10) { |
| 7624 + SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/32,pa1,pa2); |
| 7625 + SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; |
| 7626 + } else if (smallExp & 0x20) { |
| 7627 + SQR(pa1,pa2); MUL(smallExp/64,pa2,pa1); SQR(pa1,pa2); |
| 7628 + SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA; |
| 7629 + } else { |
| 7630 + ABORT; |
| 7631 + } |
| 7632 + } else { |
| 7633 + ABORT; |
| 7634 + } |
| 7635 + } |
| 7636 + |
| 7637 + res = s_mp_redc(pa1, mmm); |
| 7638 + mp_exch(pa1, result); |
| 7639 + |
| 7640 +CLEANUP: |
| 7641 + mp_clear(&accum1); |
| 7642 + mp_clear(&accum2); |
| 7643 + mp_clear(&power2); |
| 7644 + for (i = 0; i < odd_ints; ++i) { |
| 7645 + mp_clear(oddPowers + i); |
| 7646 + } |
| 7647 + return res; |
| 7648 +} |
| 7649 +#undef SQR |
| 7650 +#undef MUL |
| 7651 + |
| 7652 +#ifdef MP_USING_CACHE_SAFE_MOD_EXP |
| 7653 +unsigned int mp_using_cache_safe_exp = 1; |
| 7654 +#endif |
| 7655 + |
| 7656 +mp_err mp_set_safe_modexp(int value) |
| 7657 +{ |
| 7658 +#ifdef MP_USING_CACHE_SAFE_MOD_EXP |
| 7659 + mp_using_cache_safe_exp = value; |
| 7660 + return MP_OKAY; |
| 7661 +#else |
| 7662 + if (value == 0) { |
| 7663 + return MP_OKAY; |
| 7664 + } |
| 7665 + return MP_BADARG; |
| 7666 +#endif |
| 7667 +} |
| 7668 + |
| 7669 +#ifdef MP_USING_CACHE_SAFE_MOD_EXP |
| 7670 +#define WEAVE_WORD_SIZE 4 |
| 7671 + |
| 7672 +#ifndef MP_CHAR_STORE_SLOW |
| 7673 +/* |
| 7674 + * mpi_to_weave takes an array of bignums, a matrix in which each bignum |
| 7675 + * occupies all the columns of a row, and transposes it into a matrix in |
| 7676 + * which each bignum occupies a column of every row. The first row of the |
| 7677 + * input matrix becomes the first column of the output matrix. The n'th |
| 7678 + * row of input becomes the n'th column of output. The input data is said |
| 7679 + * to be "interleaved" or "woven" into the output matrix. |
| 7680 + * |
| 7681 + * The array of bignums is left in this woven form. Each time a single |
| 7682 + * bignum value is needed, it is recreated by fetching the n'th column, |
| 7683 + * forming a single row which is the new bignum. |
| 7684 + * |
| 7685 + * The purpose of this interleaving is make it impossible to determine which |
| 7686 + * of the bignums is being used in any one operation by examining the pattern |
| 7687 + * of cache misses. |
| 7688 + * |
| 7689 + * The weaving function does not transpose the entire input matrix in one call. |
| 7690 + * It transposes 4 rows of mp_ints into their respective columns of output. |
| 7691 + * |
| 7692 + * There are two different implementations of the weaving and unweaving code |
| 7693 + * in this file. One uses byte loads and stores. The second uses loads and |
| 7694 + * stores of mp_weave_word size values. The weaved forms of these two |
| 7695 + * implementations differ. Consequently, each one has its own explanation. |
| 7696 + * |
| 7697 + * Here is the explanation for the byte-at-a-time implementation. |
| 7698 + * |
| 7699 + * This implementation treats each mp_int bignum as an array of bytes, |
| 7700 + * rather than as an array of mp_digits. It stores those bytes as a |
| 7701 + * column of bytes in the output matrix. It doesn't care if the machine |
| 7702 + * uses big-endian or little-endian byte ordering within mp_digits. |
| 7703 + * The first byte of the mp_digit array becomes the first byte in the output |
| 7704 + * column, regardless of whether that byte is the MSB or LSB of the mp_digit. |
| 7705 + * |
| 7706 + * "bignums" is an array of mp_ints. |
| 7707 + * It points to four rows, four mp_ints, a subset of a larger array of mp_ints. |
| 7708 + * |
| 7709 + * "weaved" is the weaved output matrix. |
| 7710 + * The first byte of bignums[0] is stored in weaved[0]. |
| 7711 + * |
| 7712 + * "nBignums" is the total number of bignums in the array of which "bignums" |
| 7713 + * is a part. |
| 7714 + * |
| 7715 + * "nDigits" is the size in mp_digits of each mp_int in the "bignums" array. |
| 7716 + * mp_ints that use less than nDigits digits are logically padded with zeros |
| 7717 + * while being stored in the weaved array. |
| 7718 + */ |
| 7719 +mp_err mpi_to_weave(const mp_int *bignums, |
| 7720 + unsigned char *weaved, |
| 7721 + mp_size nDigits, /* in each mp_int of input */ |
| 7722 + mp_size nBignums) /* in the entire source array */ |
| 7723 +{ |
| 7724 + mp_size i; |
| 7725 + unsigned char * endDest = weaved + (nDigits * nBignums * sizeof(mp_digit)); |
| 7726 + |
| 7727 + for (i=0; i < WEAVE_WORD_SIZE; i++) { |
| 7728 + mp_size used = MP_USED(&bignums[i]); |
| 7729 + unsigned char *pSrc = (unsigned char *)MP_DIGITS(&bignums[i]); |
| 7730 + unsigned char *endSrc = pSrc + (used * sizeof(mp_digit)); |
| 7731 + unsigned char *pDest = weaved + i; |
| 7732 + |
| 7733 + ARGCHK(MP_SIGN(&bignums[i]) == MP_ZPOS, MP_BADARG); |
| 7734 + ARGCHK(used <= nDigits, MP_BADARG); |
| 7735 + |
| 7736 + for (; pSrc < endSrc; pSrc++) { |
| 7737 + *pDest = *pSrc; |
| 7738 + pDest += nBignums; |
| 7739 + } |
| 7740 + while (pDest < endDest) { |
| 7741 + *pDest = 0; |
| 7742 + pDest += nBignums; |
| 7743 + } |
| 7744 + } |
| 7745 + |
| 7746 + return MP_OKAY; |
| 7747 +} |
| 7748 + |
| 7749 +/* Reverse the operation above for one mp_int. |
| 7750 + * Reconstruct one mp_int from its column in the weaved array. |
| 7751 + * "pSrc" points to the offset into the weave array of the bignum we |
| 7752 + * are going to reconstruct. |
| 7753 + */ |
| 7754 +mp_err weave_to_mpi(mp_int *a, /* output, result */ |
| 7755 + const unsigned char *pSrc, /* input, byte matrix */ |
| 7756 + mp_size nDigits, /* per mp_int output */ |
| 7757 + mp_size nBignums) /* bignums in weaved matrix */ |
| 7758 +{ |
| 7759 + unsigned char *pDest = (unsigned char *)MP_DIGITS(a); |
| 7760 + unsigned char *endDest = pDest + (nDigits * sizeof(mp_digit)); |
| 7761 + |
| 7762 + MP_SIGN(a) = MP_ZPOS; |
| 7763 + MP_USED(a) = nDigits; |
| 7764 + |
| 7765 + for (; pDest < endDest; pSrc += nBignums, pDest++) { |
| 7766 + *pDest = *pSrc; |
| 7767 + } |
| 7768 + s_mp_clamp(a); |
| 7769 + return MP_OKAY; |
| 7770 +} |
| 7771 + |
| 7772 +#else |
| 7773 + |
| 7774 +/* Need a primitive that we know is 32 bits long... */ |
| 7775 +/* this is true on all modern processors we know of today*/ |
| 7776 +typedef unsigned int mp_weave_word; |
| 7777 + |
| 7778 +/* |
| 7779 + * on some platforms character stores into memory is very expensive since they |
| 7780 + * generate a read/modify/write operation on the bus. On those platforms |
| 7781 + * we need to do integer writes to the bus. Because of some unrolled code, |
| 7782 + * in this current code the size of mp_weave_word must be four. The code that |
| 7783 + * makes this assumption explicity is called out. (on some platforms a write |
| 7784 + * of 4 bytes still requires a single read-modify-write operation. |
| 7785 + * |
| 7786 + * This function is takes the identical parameters as the function above, |
| 7787 + * however it lays out the final array differently. Where the previous function |
| 7788 + * treats the mpi_int as an byte array, this function treats it as an array of |
| 7789 + * mp_digits where each digit is stored in big endian order. |
| 7790 + * |
| 7791 + * since we need to interleave on a byte by byte basis, we need to collect |
| 7792 + * several mpi structures together into a single uint32 before we write. We |
| 7793 + * also need to make sure the uint32 is arranged so that the first value of |
| 7794 + * the first array winds up in b[0]. This means construction of that uint32 |
| 7795 + * is endian specific (even though the layout of the mp_digits in the array |
| 7796 + * is always big endian). |
| 7797 + * |
| 7798 + * The final data is stored as follows : |
| 7799 + * |
| 7800 + * Our same logical array p array, m is sizeof(mp_digit), |
| 7801 + * N is still count and n is now b_size. If we define p[i].digit[j]0 as the |
| 7802 + * most significant byte of the word p[i].digit[j], p[i].digit[j]1 as |
| 7803 + * the next most significant byte of p[i].digit[j], ... and p[i].digit[j]m-1 |
| 7804 + * is the least significant byte. |
| 7805 + * Our array would look like: |
| 7806 + * p[0].digit[0]0 p[1].digit[0]0 ... p[N-2].digit[0]0 p[N-1].digit[0
]0 |
| 7807 + * p[0].digit[0]1 p[1].digit[0]1 ... p[N-2].digit[0]1 p[N-1].digit[0
]1 |
| 7808 + * . . |
| 7809 + * p[0].digit[0]m-1 p[1].digit[0]m-1 ... p[N-2].digit[0]m-1 p[N-1].digit[0
]m-1 |
| 7810 + * p[0].digit[1]0 p[1].digit[1]0 ... p[N-2].digit[1]0 p[N-1].digit[1
]0 |
| 7811 + * . . |
| 7812 + * . . |
| 7813 + * p[0].digit[n-1]m-2 p[1].digit[n-1]m-2 ... p[N-2].digit[n-1]m-2 p[N-1].digit[
n-1]m-2 |
| 7814 + * p[0].digit[n-1]m-1 p[1].digit[n-1]m-1 ... p[N-2].digit[n-1]m-1 p[N-1].digit[
n-1]m-1 |
| 7815 + * |
| 7816 + */ |
| 7817 +mp_err mpi_to_weave(const mp_int *a, unsigned char *b, |
| 7818 + mp_size b_size, mp_size count) |
| 7819 +{ |
| 7820 + mp_size i; |
| 7821 + mp_digit *digitsa0; |
| 7822 + mp_digit *digitsa1; |
| 7823 + mp_digit *digitsa2; |
| 7824 + mp_digit *digitsa3; |
| 7825 + mp_size useda0; |
| 7826 + mp_size useda1; |
| 7827 + mp_size useda2; |
| 7828 + mp_size useda3; |
| 7829 + mp_weave_word *weaved = (mp_weave_word *)b; |
| 7830 + |
| 7831 + count = count/sizeof(mp_weave_word); |
| 7832 + |
| 7833 + /* this code pretty much depends on this ! */ |
| 7834 +#if MP_ARGCHK == 2 |
| 7835 + assert(WEAVE_WORD_SIZE == 4); |
| 7836 + assert(sizeof(mp_weave_word) == 4); |
| 7837 +#endif |
| 7838 + |
| 7839 + digitsa0 = MP_DIGITS(&a[0]); |
| 7840 + digitsa1 = MP_DIGITS(&a[1]); |
| 7841 + digitsa2 = MP_DIGITS(&a[2]); |
| 7842 + digitsa3 = MP_DIGITS(&a[3]); |
| 7843 + useda0 = MP_USED(&a[0]); |
| 7844 + useda1 = MP_USED(&a[1]); |
| 7845 + useda2 = MP_USED(&a[2]); |
| 7846 + useda3 = MP_USED(&a[3]); |
| 7847 + |
| 7848 + ARGCHK(MP_SIGN(&a[0]) == MP_ZPOS, MP_BADARG); |
| 7849 + ARGCHK(MP_SIGN(&a[1]) == MP_ZPOS, MP_BADARG); |
| 7850 + ARGCHK(MP_SIGN(&a[2]) == MP_ZPOS, MP_BADARG); |
| 7851 + ARGCHK(MP_SIGN(&a[3]) == MP_ZPOS, MP_BADARG); |
| 7852 + ARGCHK(useda0 <= b_size, MP_BADARG); |
| 7853 + ARGCHK(useda1 <= b_size, MP_BADARG); |
| 7854 + ARGCHK(useda2 <= b_size, MP_BADARG); |
| 7855 + ARGCHK(useda3 <= b_size, MP_BADARG); |
| 7856 + |
| 7857 +#define SAFE_FETCH(digit, used, word) ((word) < (used) ? (digit[word]) : 0) |
| 7858 + |
| 7859 + for (i=0; i < b_size; i++) { |
| 7860 + mp_digit d0 = SAFE_FETCH(digitsa0,useda0,i); |
| 7861 + mp_digit d1 = SAFE_FETCH(digitsa1,useda1,i); |
| 7862 + mp_digit d2 = SAFE_FETCH(digitsa2,useda2,i); |
| 7863 + mp_digit d3 = SAFE_FETCH(digitsa3,useda3,i); |
| 7864 + register mp_weave_word acc; |
| 7865 + |
| 7866 +/* |
| 7867 + * ONE_STEP takes the MSB of each of our current digits and places that |
| 7868 + * byte in the appropriate position for writing to the weaved array. |
| 7869 + * On little endian: |
| 7870 + * b3 b2 b1 b0 |
| 7871 + * On big endian: |
| 7872 + * b0 b1 b2 b3 |
| 7873 + * When the data is written it would always wind up: |
| 7874 + * b[0] = b0 |
| 7875 + * b[1] = b1 |
| 7876 + * b[2] = b2 |
| 7877 + * b[3] = b3 |
| 7878 + * |
| 7879 + * Once we've written the MSB, we shift the whole digit up left one |
| 7880 + * byte, putting the Next Most Significant Byte in the MSB position, |
| 7881 + * so we we repeat the next one step that byte will be written. |
| 7882 + * NOTE: This code assumes sizeof(mp_weave_word) and MP_WEAVE_WORD_SIZE |
| 7883 + * is 4. |
| 7884 + */ |
| 7885 +#ifdef MP_IS_LITTLE_ENDIAN |
| 7886 +#define MPI_WEAVE_ONE_STEP \ |
| 7887 + acc = (d0 >> (MP_DIGIT_BIT-8)) & 0x000000ff; d0 <<= 8; /*b0*/ \ |
| 7888 + acc |= (d1 >> (MP_DIGIT_BIT-16)) & 0x0000ff00; d1 <<= 8; /*b1*/ \ |
| 7889 + acc |= (d2 >> (MP_DIGIT_BIT-24)) & 0x00ff0000; d2 <<= 8; /*b2*/ \ |
| 7890 + acc |= (d3 >> (MP_DIGIT_BIT-32)) & 0xff000000; d3 <<= 8; /*b3*/ \ |
| 7891 + *weaved = acc; weaved += count; |
| 7892 +#else |
| 7893 +#define MPI_WEAVE_ONE_STEP \ |
| 7894 + acc = (d0 >> (MP_DIGIT_BIT-32)) & 0xff000000; d0 <<= 8; /*b0*/ \ |
| 7895 + acc |= (d1 >> (MP_DIGIT_BIT-24)) & 0x00ff0000; d1 <<= 8; /*b1*/ \ |
| 7896 + acc |= (d2 >> (MP_DIGIT_BIT-16)) & 0x0000ff00; d2 <<= 8; /*b2*/ \ |
| 7897 + acc |= (d3 >> (MP_DIGIT_BIT-8)) & 0x000000ff; d3 <<= 8; /*b3*/ \ |
| 7898 + *weaved = acc; weaved += count; |
| 7899 +#endif |
| 7900 + switch (sizeof(mp_digit)) { |
| 7901 + case 32: |
| 7902 + MPI_WEAVE_ONE_STEP |
| 7903 + MPI_WEAVE_ONE_STEP |
| 7904 + MPI_WEAVE_ONE_STEP |
| 7905 + MPI_WEAVE_ONE_STEP |
| 7906 + MPI_WEAVE_ONE_STEP |
| 7907 + MPI_WEAVE_ONE_STEP |
| 7908 + MPI_WEAVE_ONE_STEP |
| 7909 + MPI_WEAVE_ONE_STEP |
| 7910 + MPI_WEAVE_ONE_STEP |
| 7911 + MPI_WEAVE_ONE_STEP |
| 7912 + MPI_WEAVE_ONE_STEP |
| 7913 + MPI_WEAVE_ONE_STEP |
| 7914 + MPI_WEAVE_ONE_STEP |
| 7915 + MPI_WEAVE_ONE_STEP |
| 7916 + MPI_WEAVE_ONE_STEP |
| 7917 + MPI_WEAVE_ONE_STEP |
| 7918 + case 16: |
| 7919 + MPI_WEAVE_ONE_STEP |
| 7920 + MPI_WEAVE_ONE_STEP |
| 7921 + MPI_WEAVE_ONE_STEP |
| 7922 + MPI_WEAVE_ONE_STEP |
| 7923 + MPI_WEAVE_ONE_STEP |
| 7924 + MPI_WEAVE_ONE_STEP |
| 7925 + MPI_WEAVE_ONE_STEP |
| 7926 + MPI_WEAVE_ONE_STEP |
| 7927 + case 8: |
| 7928 + MPI_WEAVE_ONE_STEP |
| 7929 + MPI_WEAVE_ONE_STEP |
| 7930 + MPI_WEAVE_ONE_STEP |
| 7931 + MPI_WEAVE_ONE_STEP |
| 7932 + case 4: |
| 7933 + MPI_WEAVE_ONE_STEP |
| 7934 + MPI_WEAVE_ONE_STEP |
| 7935 + case 2: |
| 7936 + MPI_WEAVE_ONE_STEP |
| 7937 + case 1: |
| 7938 + MPI_WEAVE_ONE_STEP |
| 7939 + break; |
| 7940 + } |
| 7941 + } |
| 7942 + |
| 7943 + return MP_OKAY; |
| 7944 +} |
| 7945 + |
| 7946 +/* reverse the operation above for one entry. |
| 7947 + * b points to the offset into the weave array of the power we are |
| 7948 + * calculating */ |
| 7949 +mp_err weave_to_mpi(mp_int *a, const unsigned char *b, |
| 7950 + mp_size b_size, mp_size count) |
| 7951 +{ |
| 7952 + mp_digit *pb = MP_DIGITS(a); |
| 7953 + mp_digit *end = &pb[b_size]; |
| 7954 + |
| 7955 + MP_SIGN(a) = MP_ZPOS; |
| 7956 + MP_USED(a) = b_size; |
| 7957 + |
| 7958 + for (; pb < end; pb++) { |
| 7959 + register mp_digit digit; |
| 7960 + |
| 7961 + digit = *b << 8; b += count; |
| 7962 +#define MPI_UNWEAVE_ONE_STEP digit |= *b; b += count; digit = digit << 8; |
| 7963 + switch (sizeof(mp_digit)) { |
| 7964 + case 32: |
| 7965 + MPI_UNWEAVE_ONE_STEP |
| 7966 + MPI_UNWEAVE_ONE_STEP |
| 7967 + MPI_UNWEAVE_ONE_STEP |
| 7968 + MPI_UNWEAVE_ONE_STEP |
| 7969 + MPI_UNWEAVE_ONE_STEP |
| 7970 + MPI_UNWEAVE_ONE_STEP |
| 7971 + MPI_UNWEAVE_ONE_STEP |
| 7972 + MPI_UNWEAVE_ONE_STEP |
| 7973 + MPI_UNWEAVE_ONE_STEP |
| 7974 + MPI_UNWEAVE_ONE_STEP |
| 7975 + MPI_UNWEAVE_ONE_STEP |
| 7976 + MPI_UNWEAVE_ONE_STEP |
| 7977 + MPI_UNWEAVE_ONE_STEP |
| 7978 + MPI_UNWEAVE_ONE_STEP |
| 7979 + MPI_UNWEAVE_ONE_STEP |
| 7980 + MPI_UNWEAVE_ONE_STEP |
| 7981 + case 16: |
| 7982 + MPI_UNWEAVE_ONE_STEP |
| 7983 + MPI_UNWEAVE_ONE_STEP |
| 7984 + MPI_UNWEAVE_ONE_STEP |
| 7985 + MPI_UNWEAVE_ONE_STEP |
| 7986 + MPI_UNWEAVE_ONE_STEP |
| 7987 + MPI_UNWEAVE_ONE_STEP |
| 7988 + MPI_UNWEAVE_ONE_STEP |
| 7989 + MPI_UNWEAVE_ONE_STEP |
| 7990 + case 8: |
| 7991 + MPI_UNWEAVE_ONE_STEP |
| 7992 + MPI_UNWEAVE_ONE_STEP |
| 7993 + MPI_UNWEAVE_ONE_STEP |
| 7994 + MPI_UNWEAVE_ONE_STEP |
| 7995 + case 4: |
| 7996 + MPI_UNWEAVE_ONE_STEP |
| 7997 + MPI_UNWEAVE_ONE_STEP |
| 7998 + case 2: |
| 7999 + break; |
| 8000 + } |
| 8001 + digit |= *b; b += count; |
| 8002 + |
| 8003 + *pb = digit; |
| 8004 + } |
| 8005 + s_mp_clamp(a); |
| 8006 + return MP_OKAY; |
| 8007 +} |
| 8008 +#endif |
| 8009 + |
| 8010 + |
| 8011 +#define SQR(a,b) \ |
| 8012 + MP_CHECKOK( mp_sqr(a, b) );\ |
| 8013 + MP_CHECKOK( s_mp_redc(b, mmm) ) |
| 8014 + |
| 8015 +#if defined(MP_MONT_USE_MP_MUL) |
| 8016 +#define MUL_NOWEAVE(x,a,b) \ |
| 8017 + MP_CHECKOK( mp_mul(a, x, b) ); \ |
| 8018 + MP_CHECKOK( s_mp_redc(b, mmm) ) |
| 8019 +#else |
| 8020 +#define MUL_NOWEAVE(x,a,b) \ |
| 8021 + MP_CHECKOK( s_mp_mul_mont(a, x, b, mmm) ) |
| 8022 +#endif |
| 8023 + |
| 8024 +#define MUL(x,a,b) \ |
| 8025 + MP_CHECKOK( weave_to_mpi(&tmp, powers + (x), nLen, num_powers) ); \ |
| 8026 + MUL_NOWEAVE(&tmp,a,b) |
| 8027 + |
| 8028 +#define SWAPPA ptmp = pa1; pa1 = pa2; pa2 = ptmp |
| 8029 +#define MP_ALIGN(x,y) ((((ptrdiff_t)(x))+((y)-1))&(((ptrdiff_t)0)-(y))) |
| 8030 + |
| 8031 +/* Do modular exponentiation using integer multiply code. */ |
| 8032 +mp_err mp_exptmod_safe_i(const mp_int * montBase, |
| 8033 + const mp_int * exponent, |
| 8034 + const mp_int * modulus, |
| 8035 + mp_int * result, |
| 8036 + mp_mont_modulus *mmm, |
| 8037 + int nLen, |
| 8038 + mp_size bits_in_exponent, |
| 8039 + mp_size window_bits, |
| 8040 + mp_size num_powers) |
| 8041 +{ |
| 8042 + mp_int *pa1, *pa2, *ptmp; |
| 8043 + mp_size i; |
| 8044 + mp_size first_window; |
| 8045 + mp_err res; |
| 8046 + int expOff; |
| 8047 + mp_int accum1, accum2, accum[WEAVE_WORD_SIZE]; |
| 8048 + mp_int tmp; |
| 8049 + unsigned char *powersArray; |
| 8050 + unsigned char *powers; |
| 8051 + |
| 8052 + MP_DIGITS(&accum1) = 0; |
| 8053 + MP_DIGITS(&accum2) = 0; |
| 8054 + MP_DIGITS(&accum[0]) = 0; |
| 8055 + MP_DIGITS(&accum[1]) = 0; |
| 8056 + MP_DIGITS(&accum[2]) = 0; |
| 8057 + MP_DIGITS(&accum[3]) = 0; |
| 8058 + MP_DIGITS(&tmp) = 0; |
| 8059 + |
| 8060 + powersArray = (unsigned char *)malloc(num_powers*(nLen*sizeof(mp_digit)+1)); |
| 8061 + if (powersArray == NULL) { |
| 8062 + res = MP_MEM; |
| 8063 + goto CLEANUP; |
| 8064 + } |
| 8065 + |
| 8066 + /* powers[i] = base ** (i); */ |
| 8067 + powers = (unsigned char *)MP_ALIGN(powersArray,num_powers); |
| 8068 + |
| 8069 + /* grab the first window value. This allows us to preload accumulator1 |
| 8070 + * and save a conversion, some squares and a multiple*/ |
| 8071 + MP_CHECKOK( mpl_get_bits(exponent, |
| 8072 + bits_in_exponent-window_bits, window_bits) ); |
| 8073 + first_window = (mp_size)res; |
| 8074 + |
| 8075 + MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); |
| 8076 + MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) ); |
| 8077 + MP_CHECKOK( mp_init_size(&tmp, 3 * nLen + 2) ); |
| 8078 + |
| 8079 + /* build the first WEAVE_WORD powers inline */ |
| 8080 + /* if WEAVE_WORD_SIZE is not 4, this code will have to change */ |
| 8081 + if (num_powers > 2) { |
| 8082 + MP_CHECKOK( mp_init_size(&accum[0], 3 * nLen + 2) ); |
| 8083 + MP_CHECKOK( mp_init_size(&accum[1], 3 * nLen + 2) ); |
| 8084 + MP_CHECKOK( mp_init_size(&accum[2], 3 * nLen + 2) ); |
| 8085 + MP_CHECKOK( mp_init_size(&accum[3], 3 * nLen + 2) ); |
| 8086 + mp_set(&accum[0], 1); |
| 8087 + MP_CHECKOK( s_mp_to_mont(&accum[0], mmm, &accum[0]) ); |
| 8088 + MP_CHECKOK( mp_copy(montBase, &accum[1]) ); |
| 8089 + SQR(montBase, &accum[2]); |
| 8090 + MUL_NOWEAVE(montBase, &accum[2], &accum[3]); |
| 8091 + MP_CHECKOK( mpi_to_weave(accum, powers, nLen, num_powers) ); |
| 8092 + if (first_window < 4) { |
| 8093 + MP_CHECKOK( mp_copy(&accum[first_window], &accum1) ); |
| 8094 + first_window = num_powers; |
| 8095 + } |
| 8096 + } else { |
| 8097 + if (first_window == 0) { |
| 8098 + mp_set(&accum1, 1); |
| 8099 + MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); |
| 8100 + } else { |
| 8101 + /* assert first_window == 1? */ |
| 8102 + MP_CHECKOK( mp_copy(montBase, &accum1) ); |
| 8103 + } |
| 8104 + } |
| 8105 + |
| 8106 + /* |
| 8107 + * calculate all the powers in the powers array. |
| 8108 + * this adds 2**(k-1)-2 square operations over just calculating the |
| 8109 + * odd powers where k is the window size in the two other mp_modexpt |
| 8110 + * implementations in this file. We will get some of that |
| 8111 + * back by not needing the first 'k' squares and one multiply for the |
| 8112 + * first window */ |
| 8113 + for (i = WEAVE_WORD_SIZE; i < num_powers; i++) { |
| 8114 + int acc_index = i & (WEAVE_WORD_SIZE-1); /* i % WEAVE_WORD_SIZE */ |
| 8115 + if ( i & 1 ) { |
| 8116 + MUL_NOWEAVE(montBase, &accum[acc_index-1] , &accum[acc_index]); |
| 8117 + /* we've filled the array do our 'per array' processing */ |
| 8118 + if (acc_index == (WEAVE_WORD_SIZE-1)) { |
| 8119 + MP_CHECKOK( mpi_to_weave(accum, powers + i - (WEAVE_WORD_SIZE-1), |
| 8120 + nLen, num_powers) ); |
| 8121 + |
| 8122 + if (first_window <= i) { |
| 8123 + MP_CHECKOK( mp_copy(&accum[first_window & (WEAVE_WORD_SIZE-1)], |
| 8124 + &accum1) ); |
| 8125 + first_window = num_powers; |
| 8126 + } |
| 8127 + } |
| 8128 + } else { |
| 8129 + /* up to 8 we can find 2^i-1 in the accum array, but at 8 we our source |
| 8130 + * and target are the same so we need to copy.. After that, the |
| 8131 + * value is overwritten, so we need to fetch it from the stored |
| 8132 + * weave array */ |
| 8133 + if (i > 2* WEAVE_WORD_SIZE) { |
| 8134 + MP_CHECKOK(weave_to_mpi(&accum2, powers+i/2, nLen, num_powers)); |
| 8135 + SQR(&accum2, &accum[acc_index]); |
| 8136 + } else { |
| 8137 + int half_power_index = (i/2) & (WEAVE_WORD_SIZE-1); |
| 8138 + if (half_power_index == acc_index) { |
| 8139 + /* copy is cheaper than weave_to_mpi */ |
| 8140 + MP_CHECKOK(mp_copy(&accum[half_power_index], &accum2)); |
| 8141 + SQR(&accum2,&accum[acc_index]); |
| 8142 + } else { |
| 8143 + SQR(&accum[half_power_index],&accum[acc_index]); |
| 8144 + } |
| 8145 + } |
| 8146 + } |
| 8147 + } |
| 8148 + /* if the accum1 isn't set, Then there is something wrong with our logic |
| 8149 + * above and is an internal programming error. |
| 8150 + */ |
| 8151 +#if MP_ARGCHK == 2 |
| 8152 + assert(MP_USED(&accum1) != 0); |
| 8153 +#endif |
| 8154 + |
| 8155 + /* set accumulator to montgomery residue of 1 */ |
| 8156 + pa1 = &accum1; |
| 8157 + pa2 = &accum2; |
| 8158 + |
| 8159 + for (expOff = bits_in_exponent - window_bits*2; expOff >= 0; expOff -= window
_bits) { |
| 8160 + mp_size smallExp; |
| 8161 + MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); |
| 8162 + smallExp = (mp_size)res; |
| 8163 + |
| 8164 + /* handle unroll the loops */ |
| 8165 + switch (window_bits) { |
| 8166 + case 1: |
| 8167 + if (!smallExp) { |
| 8168 + SQR(pa1,pa2); SWAPPA; |
| 8169 + } else if (smallExp & 1) { |
| 8170 + SQR(pa1,pa2); MUL_NOWEAVE(montBase,pa2,pa1); |
| 8171 + } else { |
| 8172 + ABORT; |
| 8173 + } |
| 8174 + break; |
| 8175 + case 6: |
| 8176 + SQR(pa1,pa2); SQR(pa2,pa1); |
| 8177 + /* fall through */ |
| 8178 + case 4: |
| 8179 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 8180 + MUL(smallExp, pa1,pa2); SWAPPA; |
| 8181 + break; |
| 8182 + case 5: |
| 8183 + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); |
| 8184 + SQR(pa1,pa2); MUL(smallExp,pa2,pa1); |
| 8185 + break; |
| 8186 + default: |
| 8187 + ABORT; /* could do a loop? */ |
| 8188 + } |
| 8189 + } |
| 8190 + |
| 8191 + res = s_mp_redc(pa1, mmm); |
| 8192 + mp_exch(pa1, result); |
| 8193 + |
| 8194 +CLEANUP: |
| 8195 + mp_clear(&accum1); |
| 8196 + mp_clear(&accum2); |
| 8197 + mp_clear(&accum[0]); |
| 8198 + mp_clear(&accum[1]); |
| 8199 + mp_clear(&accum[2]); |
| 8200 + mp_clear(&accum[3]); |
| 8201 + mp_clear(&tmp); |
| 8202 + /* PORT_Memset(powers,0,num_powers*nLen*sizeof(mp_digit)); */ |
| 8203 + free(powersArray); |
| 8204 + return res; |
| 8205 +} |
| 8206 +#undef SQR |
| 8207 +#undef MUL |
| 8208 +#endif |
| 8209 + |
| 8210 +mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, |
| 8211 + const mp_int *modulus, mp_int *result) |
| 8212 +{ |
| 8213 + const mp_int *base; |
| 8214 + mp_size bits_in_exponent, i, window_bits, odd_ints; |
| 8215 + mp_err res; |
| 8216 + int nLen; |
| 8217 + mp_int montBase, goodBase; |
| 8218 + mp_mont_modulus mmm; |
| 8219 +#ifdef MP_USING_CACHE_SAFE_MOD_EXP |
| 8220 + static unsigned int max_window_bits; |
| 8221 +#endif |
| 8222 + |
| 8223 + /* function for computing n0prime only works if n0 is odd */ |
| 8224 + if (!mp_isodd(modulus)) |
| 8225 + return s_mp_exptmod(inBase, exponent, modulus, result); |
| 8226 + |
| 8227 + MP_DIGITS(&montBase) = 0; |
| 8228 + MP_DIGITS(&goodBase) = 0; |
| 8229 + |
| 8230 + if (mp_cmp(inBase, modulus) < 0) { |
| 8231 + base = inBase; |
| 8232 + } else { |
| 8233 + MP_CHECKOK( mp_init(&goodBase) ); |
| 8234 + base = &goodBase; |
| 8235 + MP_CHECKOK( mp_mod(inBase, modulus, &goodBase) ); |
| 8236 + } |
| 8237 + |
| 8238 + nLen = MP_USED(modulus); |
| 8239 + MP_CHECKOK( mp_init_size(&montBase, 2 * nLen + 2) ); |
| 8240 + |
| 8241 + mmm.N = *modulus; /* a copy of the mp_int struct */ |
| 8242 + i = mpl_significant_bits(modulus); |
| 8243 + i += MP_DIGIT_BIT - 1; |
| 8244 + mmm.b = i - i % MP_DIGIT_BIT; |
| 8245 + |
| 8246 + /* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX |
| 8247 + ** where n0 = least significant mp_digit of N, the modulus. |
| 8248 + */ |
| 8249 + mmm.n0prime = 0 - s_mp_invmod_radix( MP_DIGIT(modulus, 0) ); |
| 8250 + |
| 8251 + MP_CHECKOK( s_mp_to_mont(base, &mmm, &montBase) ); |
| 8252 + |
| 8253 + bits_in_exponent = mpl_significant_bits(exponent); |
| 8254 +#ifdef MP_USING_CACHE_SAFE_MOD_EXP |
| 8255 + if (mp_using_cache_safe_exp) { |
| 8256 + if (bits_in_exponent > 780) |
| 8257 + window_bits = 6; |
| 8258 + else if (bits_in_exponent > 256) |
| 8259 + window_bits = 5; |
| 8260 + else if (bits_in_exponent > 20) |
| 8261 + window_bits = 4; |
| 8262 + /* RSA public key exponents are typically under 20 bits (common values |
| 8263 + * are: 3, 17, 65537) and a 4-bit window is inefficient |
| 8264 + */ |
| 8265 + else |
| 8266 + window_bits = 1; |
| 8267 + } else |
| 8268 +#endif |
| 8269 + if (bits_in_exponent > 480) |
| 8270 + window_bits = 6; |
| 8271 + else if (bits_in_exponent > 160) |
| 8272 + window_bits = 5; |
| 8273 + else if (bits_in_exponent > 20) |
| 8274 + window_bits = 4; |
| 8275 + /* RSA public key exponents are typically under 20 bits (common values |
| 8276 + * are: 3, 17, 65537) and a 4-bit window is inefficient |
| 8277 + */ |
| 8278 + else |
| 8279 + window_bits = 1; |
| 8280 + |
| 8281 +#ifdef MP_USING_CACHE_SAFE_MOD_EXP |
| 8282 + /* |
| 8283 + * clamp the window size based on |
| 8284 + * the cache line size. |
| 8285 + */ |
| 8286 + if (!max_window_bits) { |
| 8287 + unsigned long cache_size = s_mpi_getProcessorLineSize(); |
| 8288 + /* processor has no cache, use 'fast' code always */ |
| 8289 + if (cache_size == 0) { |
| 8290 + mp_using_cache_safe_exp = 0; |
| 8291 + } |
| 8292 + if ((cache_size == 0) || (cache_size >= 64)) { |
| 8293 + max_window_bits = 6; |
| 8294 + } else if (cache_size >= 32) { |
| 8295 + max_window_bits = 5; |
| 8296 + } else if (cache_size >= 16) { |
| 8297 + max_window_bits = 4; |
| 8298 + } else max_window_bits = 1; /* should this be an assert? */ |
| 8299 + } |
| 8300 + |
| 8301 + /* clamp the window size down before we caclulate bits_in_exponent */ |
| 8302 + if (mp_using_cache_safe_exp) { |
| 8303 + if (window_bits > max_window_bits) { |
| 8304 + window_bits = max_window_bits; |
| 8305 + } |
| 8306 + } |
| 8307 +#endif |
| 8308 + |
| 8309 + odd_ints = 1 << (window_bits - 1); |
| 8310 + i = bits_in_exponent % window_bits; |
| 8311 + if (i != 0) { |
| 8312 + bits_in_exponent += window_bits - i; |
| 8313 + } |
| 8314 + |
| 8315 +#ifdef MP_USING_MONT_MULF |
| 8316 + if (mp_using_mont_mulf) { |
| 8317 + MP_CHECKOK( s_mp_pad(&montBase, nLen) ); |
| 8318 + res = mp_exptmod_f(&montBase, exponent, modulus, result, &mmm, nLen, |
| 8319 + bits_in_exponent, window_bits, odd_ints); |
| 8320 + } else |
| 8321 +#endif |
| 8322 +#ifdef MP_USING_CACHE_SAFE_MOD_EXP |
| 8323 + if (mp_using_cache_safe_exp) { |
| 8324 + res = mp_exptmod_safe_i(&montBase, exponent, modulus, result, &mmm, nLen, |
| 8325 + bits_in_exponent, window_bits, 1 << window_bits); |
| 8326 + } else |
| 8327 +#endif |
| 8328 + res = mp_exptmod_i(&montBase, exponent, modulus, result, &mmm, nLen, |
| 8329 + bits_in_exponent, window_bits, odd_ints); |
| 8330 + |
| 8331 +CLEANUP: |
| 8332 + mp_clear(&montBase); |
| 8333 + mp_clear(&goodBase); |
| 8334 + /* Don't mp_clear mmm.N because it is merely a copy of modulus. |
| 8335 + ** Just zap it. |
| 8336 + */ |
| 8337 + memset(&mmm, 0, sizeof mmm); |
| 8338 + return res; |
| 8339 +} |
| 8340 diff --git a/net/third_party/nss/ssl/mpi/mpprime.c b/net/third_party/nss/ssl/mpi
/mpprime.c |
| 8341 new file mode 100644 |
| 8342 index 0000000..ae8e496 |
| 8343 --- /dev/null |
| 8344 +++ b/net/third_party/nss/ssl/mpi/mpprime.c |
| 8345 @@ -0,0 +1,617 @@ |
| 8346 +/* |
| 8347 + * mpprime.c |
| 8348 + * |
| 8349 + * Utilities for finding and working with prime and pseudo-prime |
| 8350 + * integers |
| 8351 + * |
| 8352 + * ***** BEGIN LICENSE BLOCK ***** |
| 8353 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 8354 + * |
| 8355 + * The contents of this file are subject to the Mozilla Public License Version |
| 8356 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 8357 + * the License. You may obtain a copy of the License at |
| 8358 + * http://www.mozilla.org/MPL/ |
| 8359 + * |
| 8360 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 8361 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 8362 + * for the specific language governing rights and limitations under the |
| 8363 + * License. |
| 8364 + * |
| 8365 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 8366 + * |
| 8367 + * The Initial Developer of the Original Code is |
| 8368 + * Michael J. Fromberger. |
| 8369 + * Portions created by the Initial Developer are Copyright (C) 1997 |
| 8370 + * the Initial Developer. All Rights Reserved. |
| 8371 + * |
| 8372 + * Contributor(s): |
| 8373 + * Netscape Communications Corporation |
| 8374 + * |
| 8375 + * Alternatively, the contents of this file may be used under the terms of |
| 8376 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 8377 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 8378 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 8379 + * of those above. If you wish to allow use of your version of this file only |
| 8380 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 8381 + * use your version of this file under the terms of the MPL, indicate your |
| 8382 + * decision by deleting the provisions above and replace them with the notice |
| 8383 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 8384 + * the provisions above, a recipient may use your version of this file under |
| 8385 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 8386 + * |
| 8387 + * ***** END LICENSE BLOCK ***** */ |
| 8388 + |
| 8389 +#include "mpi-priv.h" |
| 8390 +#include "mpprime.h" |
| 8391 +#include "mplogic.h" |
| 8392 +#include <stdlib.h> |
| 8393 +#include <string.h> |
| 8394 + |
| 8395 +#define SMALL_TABLE 0 /* determines size of hard-wired prime table */ |
| 8396 + |
| 8397 +#define RANDOM() rand() |
| 8398 + |
| 8399 +#include "primes.c" /* pull in the prime digit table */ |
| 8400 + |
| 8401 +/* |
| 8402 + Test if any of a given vector of digits divides a. If not, MP_NO |
| 8403 + is returned; otherwise, MP_YES is returned and 'which' is set to |
| 8404 + the index of the integer in the vector which divided a. |
| 8405 + */ |
| 8406 +mp_err s_mpp_divp(mp_int *a, const mp_digit *vec, int size, int *which); |
| 8407 + |
| 8408 +/* {{{ mpp_divis(a, b) */ |
| 8409 + |
| 8410 +/* |
| 8411 + mpp_divis(a, b) |
| 8412 + |
| 8413 + Returns MP_YES if a is divisible by b, or MP_NO if it is not. |
| 8414 + */ |
| 8415 + |
| 8416 +mp_err mpp_divis(mp_int *a, mp_int *b) |
| 8417 +{ |
| 8418 + mp_err res; |
| 8419 + mp_int rem; |
| 8420 + |
| 8421 + if((res = mp_init(&rem)) != MP_OKAY) |
| 8422 + return res; |
| 8423 + |
| 8424 + if((res = mp_mod(a, b, &rem)) != MP_OKAY) |
| 8425 + goto CLEANUP; |
| 8426 + |
| 8427 + if(mp_cmp_z(&rem) == 0) |
| 8428 + res = MP_YES; |
| 8429 + else |
| 8430 + res = MP_NO; |
| 8431 + |
| 8432 +CLEANUP: |
| 8433 + mp_clear(&rem); |
| 8434 + return res; |
| 8435 + |
| 8436 +} /* end mpp_divis() */ |
| 8437 + |
| 8438 +/* }}} */ |
| 8439 + |
| 8440 +/* {{{ mpp_divis_d(a, d) */ |
| 8441 + |
| 8442 +/* |
| 8443 + mpp_divis_d(a, d) |
| 8444 + |
| 8445 + Return MP_YES if a is divisible by d, or MP_NO if it is not. |
| 8446 + */ |
| 8447 + |
| 8448 +mp_err mpp_divis_d(mp_int *a, mp_digit d) |
| 8449 +{ |
| 8450 + mp_err res; |
| 8451 + mp_digit rem; |
| 8452 + |
| 8453 + ARGCHK(a != NULL, MP_BADARG); |
| 8454 + |
| 8455 + if(d == 0) |
| 8456 + return MP_NO; |
| 8457 + |
| 8458 + if((res = mp_mod_d(a, d, &rem)) != MP_OKAY) |
| 8459 + return res; |
| 8460 + |
| 8461 + if(rem == 0) |
| 8462 + return MP_YES; |
| 8463 + else |
| 8464 + return MP_NO; |
| 8465 + |
| 8466 +} /* end mpp_divis_d() */ |
| 8467 + |
| 8468 +/* }}} */ |
| 8469 + |
| 8470 +/* {{{ mpp_random(a) */ |
| 8471 + |
| 8472 +/* |
| 8473 + mpp_random(a) |
| 8474 + |
| 8475 + Assigns a random value to a. This value is generated using the |
| 8476 + standard C library's rand() function, so it should not be used for |
| 8477 + cryptographic purposes, but it should be fine for primality testing, |
| 8478 + since all we really care about there is good statistical properties. |
| 8479 + |
| 8480 + As many digits as a currently has are filled with random digits. |
| 8481 + */ |
| 8482 + |
| 8483 +mp_err mpp_random(mp_int *a) |
| 8484 + |
| 8485 +{ |
| 8486 + mp_digit next = 0; |
| 8487 + unsigned int ix, jx; |
| 8488 + |
| 8489 + ARGCHK(a != NULL, MP_BADARG); |
| 8490 + |
| 8491 + for(ix = 0; ix < USED(a); ix++) { |
| 8492 + for(jx = 0; jx < sizeof(mp_digit); jx++) { |
| 8493 + next = (next << CHAR_BIT) | (RANDOM() & UCHAR_MAX); |
| 8494 + } |
| 8495 + DIGIT(a, ix) = next; |
| 8496 + } |
| 8497 + |
| 8498 + return MP_OKAY; |
| 8499 + |
| 8500 +} /* end mpp_random() */ |
| 8501 + |
| 8502 +/* }}} */ |
| 8503 + |
| 8504 +/* {{{ mpp_random_size(a, prec) */ |
| 8505 + |
| 8506 +mp_err mpp_random_size(mp_int *a, mp_size prec) |
| 8507 +{ |
| 8508 + mp_err res; |
| 8509 + |
| 8510 + ARGCHK(a != NULL && prec > 0, MP_BADARG); |
| 8511 + |
| 8512 + if((res = s_mp_pad(a, prec)) != MP_OKAY) |
| 8513 + return res; |
| 8514 + |
| 8515 + return mpp_random(a); |
| 8516 + |
| 8517 +} /* end mpp_random_size() */ |
| 8518 + |
| 8519 +/* }}} */ |
| 8520 + |
| 8521 +/* {{{ mpp_divis_vector(a, vec, size, which) */ |
| 8522 + |
| 8523 +/* |
| 8524 + mpp_divis_vector(a, vec, size, which) |
| 8525 + |
| 8526 + Determines if a is divisible by any of the 'size' digits in vec. |
| 8527 + Returns MP_YES and sets 'which' to the index of the offending digit, |
| 8528 + if it is; returns MP_NO if it is not. |
| 8529 + */ |
| 8530 + |
| 8531 +mp_err mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which) |
| 8532 +{ |
| 8533 + ARGCHK(a != NULL && vec != NULL && size > 0, MP_BADARG); |
| 8534 + |
| 8535 + return s_mpp_divp(a, vec, size, which); |
| 8536 + |
| 8537 +} /* end mpp_divis_vector() */ |
| 8538 + |
| 8539 +/* }}} */ |
| 8540 + |
| 8541 +/* {{{ mpp_divis_primes(a, np) */ |
| 8542 + |
| 8543 +/* |
| 8544 + mpp_divis_primes(a, np) |
| 8545 + |
| 8546 + Test whether a is divisible by any of the first 'np' primes. If it |
| 8547 + is, returns MP_YES and sets *np to the value of the digit that did |
| 8548 + it. If not, returns MP_NO. |
| 8549 + */ |
| 8550 +mp_err mpp_divis_primes(mp_int *a, mp_digit *np) |
| 8551 +{ |
| 8552 + int size, which; |
| 8553 + mp_err res; |
| 8554 + |
| 8555 + ARGCHK(a != NULL && np != NULL, MP_BADARG); |
| 8556 + |
| 8557 + size = (int)*np; |
| 8558 + if(size > prime_tab_size) |
| 8559 + size = prime_tab_size; |
| 8560 + |
| 8561 + res = mpp_divis_vector(a, prime_tab, size, &which); |
| 8562 + if(res == MP_YES) |
| 8563 + *np = prime_tab[which]; |
| 8564 + |
| 8565 + return res; |
| 8566 + |
| 8567 +} /* end mpp_divis_primes() */ |
| 8568 + |
| 8569 +/* }}} */ |
| 8570 + |
| 8571 +/* {{{ mpp_fermat(a, w) */ |
| 8572 + |
| 8573 +/* |
| 8574 + Using w as a witness, try pseudo-primality testing based on Fermat's |
| 8575 + little theorem. If a is prime, and (w, a) = 1, then w^a == w (mod |
| 8576 + a). So, we compute z = w^a (mod a) and compare z to w; if they are |
| 8577 + equal, the test passes and we return MP_YES. Otherwise, we return |
| 8578 + MP_NO. |
| 8579 + */ |
| 8580 +mp_err mpp_fermat(mp_int *a, mp_digit w) |
| 8581 +{ |
| 8582 + mp_int base, test; |
| 8583 + mp_err res; |
| 8584 + |
| 8585 + if((res = mp_init(&base)) != MP_OKAY) |
| 8586 + return res; |
| 8587 + |
| 8588 + mp_set(&base, w); |
| 8589 + |
| 8590 + if((res = mp_init(&test)) != MP_OKAY) |
| 8591 + goto TEST; |
| 8592 + |
| 8593 + /* Compute test = base^a (mod a) */ |
| 8594 + if((res = mp_exptmod(&base, a, a, &test)) != MP_OKAY) |
| 8595 + goto CLEANUP; |
| 8596 + |
| 8597 + |
| 8598 + if(mp_cmp(&base, &test) == 0) |
| 8599 + res = MP_YES; |
| 8600 + else |
| 8601 + res = MP_NO; |
| 8602 + |
| 8603 + CLEANUP: |
| 8604 + mp_clear(&test); |
| 8605 + TEST: |
| 8606 + mp_clear(&base); |
| 8607 + |
| 8608 + return res; |
| 8609 + |
| 8610 +} /* end mpp_fermat() */ |
| 8611 + |
| 8612 +/* }}} */ |
| 8613 + |
| 8614 +/* |
| 8615 + Perform the fermat test on each of the primes in a list until |
| 8616 + a) one of them shows a is not prime, or |
| 8617 + b) the list is exhausted. |
| 8618 + Returns: MP_YES if it passes tests. |
| 8619 + MP_NO if fermat test reveals it is composite |
| 8620 + Some MP error code if some other error occurs. |
| 8621 + */ |
| 8622 +mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes) |
| 8623 +{ |
| 8624 + mp_err rv = MP_YES; |
| 8625 + |
| 8626 + while (nPrimes-- > 0 && rv == MP_YES) { |
| 8627 + rv = mpp_fermat(a, *primes++); |
| 8628 + } |
| 8629 + return rv; |
| 8630 +} |
| 8631 + |
| 8632 +/* {{{ mpp_pprime(a, nt) */ |
| 8633 + |
| 8634 +/* |
| 8635 + mpp_pprime(a, nt) |
| 8636 + |
| 8637 + Performs nt iteration of the Miller-Rabin probabilistic primality |
| 8638 + test on a. Returns MP_YES if the tests pass, MP_NO if one fails. |
| 8639 + If MP_NO is returned, the number is definitely composite. If MP_YES |
| 8640 + is returned, it is probably prime (but that is not guaranteed). |
| 8641 + */ |
| 8642 + |
| 8643 +mp_err mpp_pprime(mp_int *a, int nt) |
| 8644 +{ |
| 8645 + mp_err res; |
| 8646 + mp_int x, amo, m, z; /* "amo" = "a minus one" */ |
| 8647 + int iter; |
| 8648 + unsigned int jx; |
| 8649 + mp_size b; |
| 8650 + |
| 8651 + ARGCHK(a != NULL, MP_BADARG); |
| 8652 + |
| 8653 + MP_DIGITS(&x) = 0; |
| 8654 + MP_DIGITS(&amo) = 0; |
| 8655 + MP_DIGITS(&m) = 0; |
| 8656 + MP_DIGITS(&z) = 0; |
| 8657 + |
| 8658 + /* Initialize temporaries... */ |
| 8659 + MP_CHECKOK( mp_init(&amo)); |
| 8660 + /* Compute amo = a - 1 for what follows... */ |
| 8661 + MP_CHECKOK( mp_sub_d(a, 1, &amo) ); |
| 8662 + |
| 8663 + b = mp_trailing_zeros(&amo); |
| 8664 + if (!b) { /* a was even ? */ |
| 8665 + res = MP_NO; |
| 8666 + goto CLEANUP; |
| 8667 + } |
| 8668 + |
| 8669 + MP_CHECKOK( mp_init_size(&x, MP_USED(a)) ); |
| 8670 + MP_CHECKOK( mp_init(&z) ); |
| 8671 + MP_CHECKOK( mp_init(&m) ); |
| 8672 + MP_CHECKOK( mp_div_2d(&amo, b, &m, 0) ); |
| 8673 + |
| 8674 + /* Do the test nt times... */ |
| 8675 + for(iter = 0; iter < nt; iter++) { |
| 8676 + |
| 8677 + /* Choose a random value for 1 < x < a */ |
| 8678 + s_mp_pad(&x, USED(a)); |
| 8679 + mpp_random(&x); |
| 8680 + MP_CHECKOK( mp_mod(&x, a, &x) ); |
| 8681 + if(mp_cmp_d(&x, 1) <= 0) { |
| 8682 + iter--; /* don't count this iteration */ |
| 8683 + continue; /* choose a new x */ |
| 8684 + } |
| 8685 + |
| 8686 + /* Compute z = (x ** m) mod a */ |
| 8687 + MP_CHECKOK( mp_exptmod(&x, &m, a, &z) ); |
| 8688 + |
| 8689 + if(mp_cmp_d(&z, 1) == 0 || mp_cmp(&z, &amo) == 0) { |
| 8690 + res = MP_YES; |
| 8691 + continue; |
| 8692 + } |
| 8693 + |
| 8694 + res = MP_NO; /* just in case the following for loop never executes. */ |
| 8695 + for (jx = 1; jx < b; jx++) { |
| 8696 + /* z = z^2 (mod a) */ |
| 8697 + MP_CHECKOK( mp_sqrmod(&z, a, &z) ); |
| 8698 + res = MP_NO; /* previous line set res to MP_YES */ |
| 8699 + |
| 8700 + if(mp_cmp_d(&z, 1) == 0) { |
| 8701 + break; |
| 8702 + } |
| 8703 + if(mp_cmp(&z, &amo) == 0) { |
| 8704 + res = MP_YES; |
| 8705 + break; |
| 8706 + } |
| 8707 + } /* end testing loop */ |
| 8708 + |
| 8709 + /* If the test passes, we will continue iterating, but a failed |
| 8710 + test means the candidate is definitely NOT prime, so we will |
| 8711 + immediately break out of this loop |
| 8712 + */ |
| 8713 + if(res == MP_NO) |
| 8714 + break; |
| 8715 + |
| 8716 + } /* end iterations loop */ |
| 8717 + |
| 8718 +CLEANUP: |
| 8719 + mp_clear(&m); |
| 8720 + mp_clear(&z); |
| 8721 + mp_clear(&x); |
| 8722 + mp_clear(&amo); |
| 8723 + return res; |
| 8724 + |
| 8725 +} /* end mpp_pprime() */ |
| 8726 + |
| 8727 +/* }}} */ |
| 8728 + |
| 8729 +/* Produce table of composites from list of primes and trial value. |
| 8730 +** trial must be odd. List of primes must not include 2. |
| 8731 +** sieve should have dimension >= MAXPRIME/2, where MAXPRIME is largest |
| 8732 +** prime in list of primes. After this function is finished, |
| 8733 +** if sieve[i] is non-zero, then (trial + 2*i) is composite. |
| 8734 +** Each prime used in the sieve costs one division of trial, and eliminates |
| 8735 +** one or more values from the search space. (3 eliminates 1/3 of the values |
| 8736 +** alone!) Each value left in the search space costs 1 or more modular |
| 8737 +** exponentations. So, these divisions are a bargain! |
| 8738 +*/ |
| 8739 +mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes, |
| 8740 + unsigned char *sieve, mp_size nSieve) |
| 8741 +{ |
| 8742 + mp_err res; |
| 8743 + mp_digit rem; |
| 8744 + mp_size ix; |
| 8745 + unsigned long offset; |
| 8746 + |
| 8747 + memset(sieve, 0, nSieve); |
| 8748 + |
| 8749 + for(ix = 0; ix < nPrimes; ix++) { |
| 8750 + mp_digit prime = primes[ix]; |
| 8751 + mp_size i; |
| 8752 + if((res = mp_mod_d(trial, prime, &rem)) != MP_OKAY) |
| 8753 + return res; |
| 8754 + |
| 8755 + if (rem == 0) { |
| 8756 + offset = 0; |
| 8757 + } else { |
| 8758 + offset = prime - (rem / 2); |
| 8759 + } |
| 8760 + for (i = offset; i < nSieve ; i += prime) { |
| 8761 + sieve[i] = 1; |
| 8762 + } |
| 8763 + } |
| 8764 + |
| 8765 + return MP_OKAY; |
| 8766 +} |
| 8767 + |
| 8768 +#define SIEVE_SIZE 32*1024 |
| 8769 + |
| 8770 +mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong, |
| 8771 + unsigned long * nTries) |
| 8772 +{ |
| 8773 + mp_digit np; |
| 8774 + mp_err res; |
| 8775 + int i = 0; |
| 8776 + mp_int trial; |
| 8777 + mp_int q; |
| 8778 + mp_size num_tests; |
| 8779 + unsigned char *sieve; |
| 8780 + |
| 8781 + ARGCHK(start != 0, MP_BADARG); |
| 8782 + ARGCHK(nBits > 16, MP_RANGE); |
| 8783 + |
| 8784 + sieve = malloc(SIEVE_SIZE); |
| 8785 + ARGCHK(sieve != NULL, MP_MEM); |
| 8786 + |
| 8787 + MP_DIGITS(&trial) = 0; |
| 8788 + MP_DIGITS(&q) = 0; |
| 8789 + MP_CHECKOK( mp_init(&trial) ); |
| 8790 + MP_CHECKOK( mp_init(&q) ); |
| 8791 + /* values taken from table 4.4, HandBook of Applied Cryptography */ |
| 8792 + if (nBits >= 1300) { |
| 8793 + num_tests = 2; |
| 8794 + } else if (nBits >= 850) { |
| 8795 + num_tests = 3; |
| 8796 + } else if (nBits >= 650) { |
| 8797 + num_tests = 4; |
| 8798 + } else if (nBits >= 550) { |
| 8799 + num_tests = 5; |
| 8800 + } else if (nBits >= 450) { |
| 8801 + num_tests = 6; |
| 8802 + } else if (nBits >= 400) { |
| 8803 + num_tests = 7; |
| 8804 + } else if (nBits >= 350) { |
| 8805 + num_tests = 8; |
| 8806 + } else if (nBits >= 300) { |
| 8807 + num_tests = 9; |
| 8808 + } else if (nBits >= 250) { |
| 8809 + num_tests = 12; |
| 8810 + } else if (nBits >= 200) { |
| 8811 + num_tests = 15; |
| 8812 + } else if (nBits >= 150) { |
| 8813 + num_tests = 18; |
| 8814 + } else if (nBits >= 100) { |
| 8815 + num_tests = 27; |
| 8816 + } else |
| 8817 + num_tests = 50; |
| 8818 + |
| 8819 + if (strong) |
| 8820 + --nBits; |
| 8821 + MP_CHECKOK( mpl_set_bit(start, nBits - 1, 1) ); |
| 8822 + MP_CHECKOK( mpl_set_bit(start, 0, 1) ); |
| 8823 + for (i = mpl_significant_bits(start) - 1; i >= nBits; --i) { |
| 8824 + MP_CHECKOK( mpl_set_bit(start, i, 0) ); |
| 8825 + } |
| 8826 + /* start sieveing with prime value of 3. */ |
| 8827 + MP_CHECKOK(mpp_sieve(start, prime_tab + 1, prime_tab_size - 1, |
| 8828 + sieve, SIEVE_SIZE) ); |
| 8829 + |
| 8830 +#ifdef DEBUG_SIEVE |
| 8831 + res = 0; |
| 8832 + for (i = 0; i < SIEVE_SIZE; ++i) { |
| 8833 + if (!sieve[i]) |
| 8834 + ++res; |
| 8835 + } |
| 8836 + fprintf(stderr,"sieve found %d potential primes.\n", res); |
| 8837 +#define FPUTC(x,y) fputc(x,y) |
| 8838 +#else |
| 8839 +#define FPUTC(x,y) |
| 8840 +#endif |
| 8841 + |
| 8842 + res = MP_NO; |
| 8843 + for(i = 0; i < SIEVE_SIZE; ++i) { |
| 8844 + if (sieve[i]) /* this number is composite */ |
| 8845 + continue; |
| 8846 + MP_CHECKOK( mp_add_d(start, 2 * i, &trial) ); |
| 8847 + FPUTC('.', stderr); |
| 8848 + /* run a Fermat test */ |
| 8849 + res = mpp_fermat(&trial, 2); |
| 8850 + if (res != MP_OKAY) { |
| 8851 + if (res == MP_NO) |
| 8852 + continue; /* was composite */ |
| 8853 + goto CLEANUP; |
| 8854 + } |
| 8855 + |
| 8856 + FPUTC('+', stderr); |
| 8857 + /* If that passed, run some Miller-Rabin tests */ |
| 8858 + res = mpp_pprime(&trial, num_tests); |
| 8859 + if (res != MP_OKAY) { |
| 8860 + if (res == MP_NO) |
| 8861 + continue; /* was composite */ |
| 8862 + goto CLEANUP; |
| 8863 + } |
| 8864 + FPUTC('!', stderr); |
| 8865 + |
| 8866 + if (!strong) |
| 8867 + break; /* success !! */ |
| 8868 + |
| 8869 + /* At this point, we have strong evidence that our candidate |
| 8870 + is itself prime. If we want a strong prime, we need now |
| 8871 + to test q = 2p + 1 for primality... |
| 8872 + */ |
| 8873 + MP_CHECKOK( mp_mul_2(&trial, &q) ); |
| 8874 + MP_CHECKOK( mp_add_d(&q, 1, &q) ); |
| 8875 + |
| 8876 + /* Test q for small prime divisors ... */ |
| 8877 + np = prime_tab_size; |
| 8878 + res = mpp_divis_primes(&q, &np); |
| 8879 + if (res == MP_YES) { /* is composite */ |
| 8880 + mp_clear(&q); |
| 8881 + continue; |
| 8882 + } |
| 8883 + if (res != MP_NO) |
| 8884 + goto CLEANUP; |
| 8885 + |
| 8886 + /* And test with Fermat, as with its parent ... */ |
| 8887 + res = mpp_fermat(&q, 2); |
| 8888 + if (res != MP_YES) { |
| 8889 + mp_clear(&q); |
| 8890 + if (res == MP_NO) |
| 8891 + continue; /* was composite */ |
| 8892 + goto CLEANUP; |
| 8893 + } |
| 8894 + |
| 8895 + /* And test with Miller-Rabin, as with its parent ... */ |
| 8896 + res = mpp_pprime(&q, num_tests); |
| 8897 + if (res != MP_YES) { |
| 8898 + mp_clear(&q); |
| 8899 + if (res == MP_NO) |
| 8900 + continue; /* was composite */ |
| 8901 + goto CLEANUP; |
| 8902 + } |
| 8903 + |
| 8904 + /* If it passed, we've got a winner */ |
| 8905 + mp_exch(&q, &trial); |
| 8906 + mp_clear(&q); |
| 8907 + break; |
| 8908 + |
| 8909 + } /* end of loop through sieved values */ |
| 8910 + if (res == MP_YES) |
| 8911 + mp_exch(&trial, start); |
| 8912 +CLEANUP: |
| 8913 + mp_clear(&trial); |
| 8914 + mp_clear(&q); |
| 8915 + if (nTries) |
| 8916 + *nTries += i; |
| 8917 + if (sieve != NULL) { |
| 8918 + memset(sieve, 0, SIEVE_SIZE); |
| 8919 + free (sieve); |
| 8920 + } |
| 8921 + return res; |
| 8922 +} |
| 8923 + |
| 8924 +/*========================================================================*/ |
| 8925 +/*------------------------------------------------------------------------*/ |
| 8926 +/* Static functions visible only to the library internally */ |
| 8927 + |
| 8928 +/* {{{ s_mpp_divp(a, vec, size, which) */ |
| 8929 + |
| 8930 +/* |
| 8931 + Test for divisibility by members of a vector of digits. Returns |
| 8932 + MP_NO if a is not divisible by any of them; returns MP_YES and sets |
| 8933 + 'which' to the index of the offender, if it is. Will stop on the |
| 8934 + first digit against which a is divisible. |
| 8935 + */ |
| 8936 + |
| 8937 +mp_err s_mpp_divp(mp_int *a, const mp_digit *vec, int size, int *which) |
| 8938 +{ |
| 8939 + mp_err res; |
| 8940 + mp_digit rem; |
| 8941 + |
| 8942 + int ix; |
| 8943 + |
| 8944 + for(ix = 0; ix < size; ix++) { |
| 8945 + if((res = mp_mod_d(a, vec[ix], &rem)) != MP_OKAY) |
| 8946 + return res; |
| 8947 + |
| 8948 + if(rem == 0) { |
| 8949 + if(which) |
| 8950 + *which = ix; |
| 8951 + return MP_YES; |
| 8952 + } |
| 8953 + } |
| 8954 + |
| 8955 + return MP_NO; |
| 8956 + |
| 8957 +} /* end s_mpp_divp() */ |
| 8958 + |
| 8959 +/* }}} */ |
| 8960 + |
| 8961 +/*------------------------------------------------------------------------*/ |
| 8962 +/* HERE THERE BE DRAGONS */ |
| 8963 diff --git a/net/third_party/nss/ssl/mpi/mpprime.h b/net/third_party/nss/ssl/mpi
/mpprime.h |
| 8964 new file mode 100644 |
| 8965 index 0000000..486d4a1 |
| 8966 --- /dev/null |
| 8967 +++ b/net/third_party/nss/ssl/mpi/mpprime.h |
| 8968 @@ -0,0 +1,70 @@ |
| 8969 +/* |
| 8970 + * mpprime.h |
| 8971 + * |
| 8972 + * Utilities for finding and working with prime and pseudo-prime |
| 8973 + * integers |
| 8974 + * |
| 8975 + * ***** BEGIN LICENSE BLOCK ***** |
| 8976 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 8977 + * |
| 8978 + * The contents of this file are subject to the Mozilla Public License Version |
| 8979 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 8980 + * the License. You may obtain a copy of the License at |
| 8981 + * http://www.mozilla.org/MPL/ |
| 8982 + * |
| 8983 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 8984 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 8985 + * for the specific language governing rights and limitations under the |
| 8986 + * License. |
| 8987 + * |
| 8988 + * The Original Code is the MPI Arbitrary Precision Integer Arithmetic library. |
| 8989 + * |
| 8990 + * The Initial Developer of the Original Code is |
| 8991 + * Michael J. Fromberger. |
| 8992 + * Portions created by the Initial Developer are Copyright (C) 1997 |
| 8993 + * the Initial Developer. All Rights Reserved. |
| 8994 + * |
| 8995 + * Contributor(s): |
| 8996 + * |
| 8997 + * Alternatively, the contents of this file may be used under the terms of |
| 8998 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 8999 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 9000 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 9001 + * of those above. If you wish to allow use of your version of this file only |
| 9002 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 9003 + * use your version of this file under the terms of the MPL, indicate your |
| 9004 + * decision by deleting the provisions above and replace them with the notice |
| 9005 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 9006 + * the provisions above, a recipient may use your version of this file under |
| 9007 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 9008 + * |
| 9009 + * ***** END LICENSE BLOCK ***** */ |
| 9010 + |
| 9011 +#ifndef _H_MP_PRIME_ |
| 9012 +#define _H_MP_PRIME_ |
| 9013 + |
| 9014 +#include "mpi.h" |
| 9015 + |
| 9016 +extern const int prime_tab_size; /* number of primes available */ |
| 9017 +extern const mp_digit prime_tab[]; |
| 9018 + |
| 9019 +/* Tests for divisibility */ |
| 9020 +mp_err mpp_divis(mp_int *a, mp_int *b); |
| 9021 +mp_err mpp_divis_d(mp_int *a, mp_digit d); |
| 9022 + |
| 9023 +/* Random selection */ |
| 9024 +mp_err mpp_random(mp_int *a); |
| 9025 +mp_err mpp_random_size(mp_int *a, mp_size prec); |
| 9026 + |
| 9027 +/* Pseudo-primality testing */ |
| 9028 +mp_err mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which); |
| 9029 +mp_err mpp_divis_primes(mp_int *a, mp_digit *np); |
| 9030 +mp_err mpp_fermat(mp_int *a, mp_digit w); |
| 9031 +mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes); |
| 9032 +mp_err mpp_pprime(mp_int *a, int nt); |
| 9033 +mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes, |
| 9034 + unsigned char *sieve, mp_size nSieve); |
| 9035 +mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong, |
| 9036 + unsigned long * nTries); |
| 9037 + |
| 9038 +#endif /* end _H_MP_PRIME_ */ |
| 9039 diff --git a/net/third_party/nss/ssl/mpi/secmpi.h b/net/third_party/nss/ssl/mpi/
secmpi.h |
| 9040 new file mode 100644 |
| 9041 index 0000000..e343fb8 |
| 9042 --- /dev/null |
| 9043 +++ b/net/third_party/nss/ssl/mpi/secmpi.h |
| 9044 @@ -0,0 +1,61 @@ |
| 9045 +/* ***** BEGIN LICENSE BLOCK ***** |
| 9046 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 9047 + * |
| 9048 + * The contents of this file are subject to the Mozilla Public License Version |
| 9049 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 9050 + * the License. You may obtain a copy of the License at |
| 9051 + * http://www.mozilla.org/MPL/ |
| 9052 + * |
| 9053 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 9054 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 9055 + * for the specific language governing rights and limitations under the |
| 9056 + * License. |
| 9057 + * |
| 9058 + * The Original Code is the Netscape security libraries. |
| 9059 + * |
| 9060 + * The Initial Developer of the Original Code is |
| 9061 + * Netscape Communications Corporation. |
| 9062 + * Portions created by the Initial Developer are Copyright (C) 1994-2000 |
| 9063 + * the Initial Developer. All Rights Reserved. |
| 9064 + * |
| 9065 + * Contributor(s): |
| 9066 + * |
| 9067 + * Alternatively, the contents of this file may be used under the terms of |
| 9068 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 9069 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 9070 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 9071 + * of those above. If you wish to allow use of your version of this file only |
| 9072 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 9073 + * use your version of this file under the terms of the MPL, indicate your |
| 9074 + * decision by deleting the provisions above and replace them with the notice |
| 9075 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 9076 + * the provisions above, a recipient may use your version of this file under |
| 9077 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 9078 + * |
| 9079 + * ***** END LICENSE BLOCK ***** */ |
| 9080 + |
| 9081 +#include "mpi.h" |
| 9082 + |
| 9083 +#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup |
| 9084 + |
| 9085 +#define CHECK_MPI_OK(func) if (MP_OKAY > (err = func)) goto cleanup |
| 9086 + |
| 9087 +#define OCTETS_TO_MPINT(oc, mp, len) \ |
| 9088 + CHECK_MPI_OK(mp_read_unsigned_octets((mp), oc, len)) |
| 9089 + |
| 9090 +#define SECITEM_TO_MPINT(it, mp) \ |
| 9091 + CHECK_MPI_OK(mp_read_unsigned_octets((mp), (it).data, (it).len)) |
| 9092 + |
| 9093 +#define MPINT_TO_SECITEM(mp, it, arena) \ |
| 9094 + SECITEM_AllocItem(arena, (it), mp_unsigned_octet_size(mp)); \ |
| 9095 + if ((it)->data == NULL) {err = MP_MEM; goto cleanup;} \ |
| 9096 + err = mp_to_unsigned_octets(mp, (it)->data, (it)->len); \ |
| 9097 + if (err < 0) goto cleanup; else err = MP_OKAY; |
| 9098 + |
| 9099 +#define MP_TO_SEC_ERROR(err) \ |
| 9100 + switch (err) { \ |
| 9101 + case MP_MEM: PORT_SetError(SEC_ERROR_NO_MEMORY); break; \ |
| 9102 + case MP_RANGE: PORT_SetError(SEC_ERROR_BAD_DATA); break; \ |
| 9103 + case MP_BADARG: PORT_SetError(SEC_ERROR_INVALID_ARGS); break; \ |
| 9104 + default: PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); break; \ |
| 9105 + } |
| 9106 diff --git a/net/third_party/nss/ssl/srp.c b/net/third_party/nss/ssl/srp.c |
| 9107 new file mode 100644 |
| 9108 index 0000000..a1cb96c |
| 9109 --- /dev/null |
| 9110 +++ b/net/third_party/nss/ssl/srp.c |
| 9111 @@ -0,0 +1,550 @@ |
| 9112 +/* ***** BEGIN LICENSE BLOCK ***** |
| 9113 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 9114 + * |
| 9115 + * The contents of this file are subject to the Mozilla Public License Version |
| 9116 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 9117 + * the License. You may obtain a copy of the License at |
| 9118 + * http://www.mozilla.org/MPL/ |
| 9119 + * |
| 9120 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 9121 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 9122 + * for the specific language governing rights and limitations under the |
| 9123 + * License. |
| 9124 + * |
| 9125 + * The Initial Developer of the Original Code is |
| 9126 + * Steffen Schulz - pepe (at) cbg.dyndns.org |
| 9127 + * |
| 9128 + * Portions created by the Initial Developer are Copyright (C) 2007 |
| 9129 + * the Initial Developer. All Rights Reserved. |
| 9130 + * |
| 9131 + * Contributor(s): |
| 9132 + * |
| 9133 + * Alternatively, the contents of this file may be used under the terms of |
| 9134 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 9135 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 9136 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 9137 + * of those above. If you wish to allow use of your version of this file only |
| 9138 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 9139 + * use your version of this file under the terms of the MPL, indicate your |
| 9140 + * decision by deleting the provisions above and replace them with the notice |
| 9141 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 9142 + * the provisions above, a recipient may use your version of this file under |
| 9143 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 9144 + * |
| 9145 + * ***** END LICENSE BLOCK ***** */ |
| 9146 + |
| 9147 +/* |
| 9148 + * This file implements the core SRP algorithms described in rfc 5054 |
| 9149 + * for enabling secure password based authentication in TLS via SRP. |
| 9150 + * |
| 9151 + * See also: |
| 9152 + * Wu, T., "SRP-6: Improvements and Refinements to the Secure |
| 9153 + * Remote Password Protocol", October 2002, |
| 9154 + * <http://srp.stanford.edu/srp6.ps>. |
| 9155 + */ |
| 9156 + |
| 9157 +#ifdef FREEBL_NO_DEPEND |
| 9158 +#include "stubs.h" |
| 9159 +#endif |
| 9160 + |
| 9161 +#include "secerr.h" |
| 9162 +#include "blapi.h" |
| 9163 +#include "mpi/mpi.h" |
| 9164 +#include "mpi/secmpi.h" |
| 9165 +#include "secitem.h" |
| 9166 +#include "keythi.h" |
| 9167 +#include "plbase64.h" |
| 9168 + |
| 9169 +#include "srp_groups.h" |
| 9170 + |
| 9171 +/* length of srp secret keys in byte */ |
| 9172 +#define SRP_SECRET_KEY_LEN 32 |
| 9173 + |
| 9174 + |
| 9175 +/* check if (N,g) are among the known-good group params */ |
| 9176 +static SECStatus check_srp_group(const mp_int *N, const mp_int *g) { |
| 9177 + int i; |
| 9178 + char *N_str; |
| 9179 + char *g_str; |
| 9180 + mp_err err; |
| 9181 + SECStatus rv = SECFailure; |
| 9182 + |
| 9183 + N_str = PORT_Alloc(mp_radix_size(N, 16)); |
| 9184 + g_str = PORT_Alloc(mp_radix_size(g, 16)); |
| 9185 + |
| 9186 + CHECK_MPI_OK(mp_toradix(N, N_str, 16)); |
| 9187 + CHECK_MPI_OK(mp_toradix(g, g_str, 16)); |
| 9188 + |
| 9189 + /* compare bytes and length */ |
| 9190 + for ( i=0; i < SRP_KNOWN_GROUPS; i++) |
| 9191 + if (PORT_Strcmp(N_str, known_srp_groups[i].modulus)) |
| 9192 + if (PORT_Strcmp(g_str, known_srp_groups[i].generator)) { |
| 9193 + rv = SECSuccess; |
| 9194 + break; |
| 9195 + } |
| 9196 + |
| 9197 + if (rv !=SECSuccess) |
| 9198 + PORT_SetError(SEC_ERROR_SRP_UNSUPPORTED_GROUP); |
| 9199 + |
| 9200 +cleanup: |
| 9201 + PORT_Free(N_str); |
| 9202 + PORT_Free(g_str); |
| 9203 + if (err) { |
| 9204 + MP_TO_SEC_ERROR(err); |
| 9205 + rv = SECFailure; |
| 9206 + } |
| 9207 + |
| 9208 + return rv; |
| 9209 +} |
| 9210 + |
| 9211 +/* check if B%N = 0 -> trapdoor */ |
| 9212 +static SECStatus srp_backdoor_check(const mp_int *N, const mp_int *B) { |
| 9213 + |
| 9214 + mp_int res; |
| 9215 + mp_err err; |
| 9216 + |
| 9217 + CHECK_MPI_OK(mp_init(&res)); |
| 9218 + CHECK_MPI_OK(mp_mod(B, N, &res)); |
| 9219 + |
| 9220 + |
| 9221 + if ( mp_cmp_z(&res) == 0) { |
| 9222 + PORT_SetError(SEC_ERROR_SRP_ILLEGAL_PARAMETER); |
| 9223 + return SECFailure; |
| 9224 + } |
| 9225 +cleanup: |
| 9226 + mp_clear(&res); |
| 9227 + if (err) { |
| 9228 + MP_TO_SEC_ERROR(err); |
| 9229 + return SECFailure; |
| 9230 + } |
| 9231 + return SECSuccess; |
| 9232 +} |
| 9233 + |
| 9234 +/* SRP_DeriveKey computes common key 'pms' |
| 9235 + * |
| 9236 + * The pre-master secret is calculated as follows: |
| 9237 + * |
| 9238 + * u = SHA1(PAD(A) | PAD(B)) |
| 9239 + * k = SHA1(N | PAD(g)) |
| 9240 + * pms = (A * v^u) ^ b % N |
| 9241 + * |
| 9242 + * PAD() left-paddes with \0 until length of N |
| 9243 + */ |
| 9244 + |
| 9245 +SECStatus SRP_ServerDerive(SRPPrivateKey *prvKey, SRPDeriveParams *srp, |
| 9246 + SECItem *pms) { |
| 9247 + mp_int mp_pms, mp_res; |
| 9248 + mp_int mp_A, mp_b, mp_v; |
| 9249 + mp_int mp_N, mp_g, mp_u, mp_k; |
| 9250 + SECItem *it_u, *it_k; |
| 9251 + unsigned char *zero; |
| 9252 + unsigned int len = srp->N.len; |
| 9253 + SHA1Context *ctx = SHA1_NewContext(); |
| 9254 + SECStatus rv = SECFailure; |
| 9255 + mp_err err = MP_OKAY; |
| 9256 + |
| 9257 + CHECK_MPI_OK(mp_init(&mp_N)); |
| 9258 + CHECK_MPI_OK(mp_init(&mp_g)); |
| 9259 + CHECK_MPI_OK(mp_init(&mp_u)); |
| 9260 + CHECK_MPI_OK(mp_init(&mp_k)); |
| 9261 + CHECK_MPI_OK(mp_init(&mp_v)); |
| 9262 + CHECK_MPI_OK(mp_init(&mp_b)); |
| 9263 + CHECK_MPI_OK(mp_init(&mp_A)); |
| 9264 + CHECK_MPI_OK(mp_init(&mp_res)); |
| 9265 + CHECK_MPI_OK(mp_init(&mp_pms)); |
| 9266 + |
| 9267 + zero = PORT_ZAlloc(len); |
| 9268 + it_u = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); |
| 9269 + it_k = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); |
| 9270 + |
| 9271 + if (!zero || !it_u || !it_k) { |
| 9272 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9273 + goto cleanup; |
| 9274 + } |
| 9275 + |
| 9276 + /* u = SHA1( PAD(A) | PAD(B) ) */ |
| 9277 + SHA1_Begin(ctx); |
| 9278 + SHA1_Update(ctx, zero, len - srp->ppub.len); |
| 9279 + SHA1_Update(ctx, srp->ppub.data, srp->ppub.len); |
| 9280 + SHA1_Update(ctx, zero, len - prvKey->pubKey.len); |
| 9281 + SHA1_Update(ctx, prvKey->pubKey.data, prvKey->pubKey.len); |
| 9282 + SHA1_End(ctx, it_u->data, &it_u->len, SHA1_LENGTH); |
| 9283 + |
| 9284 + /* k = SHA1( N | PAD(g) ) */ |
| 9285 + SHA1_Begin(ctx); |
| 9286 + SHA1_Update(ctx, srp->N.data, srp->N.len); |
| 9287 + SHA1_Update(ctx, zero, len - srp->g.len); |
| 9288 + SHA1_Update(ctx, srp->g.data, srp->g.len); |
| 9289 + SHA1_End(ctx, it_k->data, &it_k->len, SHA1_LENGTH); |
| 9290 + |
| 9291 + /* |
| 9292 + * calculate pms = (A * v^u) ^ b % N |
| 9293 + */ |
| 9294 + |
| 9295 + SECITEM_TO_MPINT(*it_u, &mp_u); |
| 9296 + SECITEM_TO_MPINT(*it_k, &mp_k); |
| 9297 + SECITEM_TO_MPINT(srp->N, &mp_N); |
| 9298 + SECITEM_TO_MPINT(srp->g, &mp_g); |
| 9299 + SECITEM_TO_MPINT(srp->ppub,&mp_A); |
| 9300 + SECITEM_TO_MPINT(prvKey->secret, &mp_v); |
| 9301 + SECITEM_TO_MPINT(prvKey->prvKey, &mp_b); |
| 9302 + |
| 9303 + CHECK_MPI_OK(mp_exptmod(&mp_v, &mp_u, &mp_N, &mp_res)); |
| 9304 + CHECK_MPI_OK(mp_mulmod(&mp_A, &mp_res, &mp_N, &mp_res)); |
| 9305 + CHECK_MPI_OK(mp_exptmod(&mp_res, &mp_b, &mp_N, &mp_pms)); |
| 9306 + |
| 9307 + MPINT_TO_SECITEM(&mp_pms, pms, NULL); |
| 9308 + |
| 9309 + rv = SECSuccess; |
| 9310 +cleanup: |
| 9311 + PORT_Free(zero); |
| 9312 + SECITEM_FreeItem(it_u, PR_TRUE); |
| 9313 + SECITEM_FreeItem(it_k, PR_TRUE); |
| 9314 + SHA1_DestroyContext(ctx, PR_TRUE); |
| 9315 + mp_clear(&mp_N); |
| 9316 + mp_clear(&mp_g); |
| 9317 + mp_clear(&mp_b); |
| 9318 + mp_clear(&mp_A); |
| 9319 + mp_clear(&mp_k); |
| 9320 + mp_clear(&mp_u); |
| 9321 + mp_clear(&mp_v); |
| 9322 + mp_clear(&mp_pms); |
| 9323 + mp_clear(&mp_res); |
| 9324 + if (err) { |
| 9325 + MP_TO_SEC_ERROR(err); |
| 9326 + rv = SECFailure; |
| 9327 + } |
| 9328 + return rv; |
| 9329 +} |
| 9330 + |
| 9331 +/* SRP_ClientDerive, computes common key 'pms' |
| 9332 + * |
| 9333 + * The pre-master secret is calculated as follows: |
| 9334 + * |
| 9335 + * u = SHA1(PAD(A) | PAD(B)) |
| 9336 + * k = SHA1(N | PAD(g)) |
| 9337 + * x = SHA1(s | SHA1(I | ":" | P)) |
| 9338 + * pms = (B - (k * g^x)) ^ (a + (u * x)) % N |
| 9339 + * |
| 9340 + * PAD() left-paddes with \0 until length of N |
| 9341 + */ |
| 9342 +SECStatus SRP_ClientDerive(SRPPrivateKey *prvKey, SRPDeriveParams *srp, |
| 9343 + SECItem * pms) { |
| 9344 + |
| 9345 + /* mp_int use pointers*/ |
| 9346 + unsigned char *zero = NULL; |
| 9347 + mp_int mp_pms, mp_res1, mp_res2; |
| 9348 + mp_int mp_B, mp_a, mp_A; |
| 9349 + mp_int mp_N, mp_g, mp_u; |
| 9350 + mp_int mp_k, mp_x; |
| 9351 + mp_err err = MP_OKAY; |
| 9352 + SECItem *it_u = NULL; |
| 9353 + SECItem *it_k = NULL; |
| 9354 + SECItem *it_x = NULL; |
| 9355 + SHA1Context *ctx = SHA1_NewContext(); |
| 9356 + unsigned int len = srp->N.len; |
| 9357 + SECStatus rv = SECFailure; |
| 9358 + |
| 9359 + if (prvKey->secret.len == 0) { |
| 9360 + /* XXX this error is probably meant for token passwords |
| 9361 + * anyway, we use it to show missing password in bypass mode*/ |
| 9362 + PORT_SetError(SEC_ERROR_BAD_PASSWORD); |
| 9363 + return SECFailure; |
| 9364 + } |
| 9365 + |
| 9366 + CHECK_MPI_OK(mp_init(&mp_N)); |
| 9367 + CHECK_MPI_OK(mp_init(&mp_g)); |
| 9368 + CHECK_MPI_OK(mp_init(&mp_u)); |
| 9369 + CHECK_MPI_OK(mp_init(&mp_k)); |
| 9370 + CHECK_MPI_OK(mp_init(&mp_x)); |
| 9371 + CHECK_MPI_OK(mp_init(&mp_A)); |
| 9372 + CHECK_MPI_OK(mp_init(&mp_a)); |
| 9373 + CHECK_MPI_OK(mp_init(&mp_B)); |
| 9374 + CHECK_MPI_OK(mp_init(&mp_res1)); |
| 9375 + CHECK_MPI_OK(mp_init(&mp_res2)); |
| 9376 + CHECK_MPI_OK(mp_init(&mp_pms)); |
| 9377 + |
| 9378 + /* check server-supplied parameters */ |
| 9379 + SECITEM_TO_MPINT(srp->N, &mp_N); |
| 9380 + SECITEM_TO_MPINT(srp->g, &mp_g); |
| 9381 + SECITEM_TO_MPINT(srp->ppub,&mp_B); |
| 9382 + |
| 9383 + CHECK_SEC_OK(srp_backdoor_check(&mp_N, &mp_B)); |
| 9384 + |
| 9385 + /* |
| 9386 + * create hashed variables u, k, x |
| 9387 + */ |
| 9388 + |
| 9389 + zero = PORT_ZAlloc(len); |
| 9390 + it_u = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); |
| 9391 + it_k = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); |
| 9392 + it_x = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); |
| 9393 + |
| 9394 + if (!zero || !it_u || !it_k || !it_x) { |
| 9395 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9396 + goto cleanup; |
| 9397 + } |
| 9398 + |
| 9399 + /* u = SHA1( PAD(A) | PAD(B) ) */ |
| 9400 + SHA1_Begin(ctx); |
| 9401 + SHA1_Update(ctx, zero, len - prvKey->pubKey.len); |
| 9402 + SHA1_Update(ctx, prvKey->pubKey.data, prvKey->pubKey.len); |
| 9403 + SHA1_Update(ctx, zero, len - srp->ppub.len); |
| 9404 + SHA1_Update(ctx, srp->ppub.data, srp->ppub.len); |
| 9405 + SHA1_End(ctx, it_u->data, &it_u->len, SHA1_LENGTH); |
| 9406 + |
| 9407 + /* k = SHA1( N | PAD(g) ) */ |
| 9408 + SHA1_Begin(ctx); |
| 9409 + SHA1_Update(ctx, srp->N.data, srp->N.len); |
| 9410 + SHA1_Update(ctx, zero, len - srp->g.len); |
| 9411 + SHA1_Update(ctx, srp->g.data, srp->g.len); |
| 9412 + SHA1_End(ctx, it_k->data, &it_k->len, SHA1_LENGTH); |
| 9413 + |
| 9414 + /* x = SHA1(s | SHA1(I | ":" | P)) */ |
| 9415 + SHA1_Begin(ctx); |
| 9416 + SHA1_Update(ctx, srp->u.data, srp->u.len); |
| 9417 + SHA1_Update(ctx,(unsigned char *)":",1); |
| 9418 + SHA1_Update(ctx, prvKey->secret.data, prvKey->secret.len); |
| 9419 + SHA1_End(ctx, it_x->data, &it_x->len, SHA1_LENGTH); |
| 9420 + |
| 9421 + SHA1_Begin(ctx); |
| 9422 + SHA1_Update(ctx, srp->s.data, srp->s.len); |
| 9423 + SHA1_Update(ctx, it_x->data, it_x->len); |
| 9424 + SHA1_End(ctx, it_x->data, &it_x->len, SHA1_LENGTH); |
| 9425 + |
| 9426 + /* |
| 9427 + * compute pms = (B - (k * g^x)) ^ (a + (u * x)) % N |
| 9428 + */ |
| 9429 + |
| 9430 + SECITEM_TO_MPINT(*it_u, &mp_u); |
| 9431 + SECITEM_TO_MPINT(*it_k, &mp_k); |
| 9432 + SECITEM_TO_MPINT(*it_x, &mp_x); |
| 9433 + SECITEM_TO_MPINT(prvKey->prvKey, &mp_a); |
| 9434 + |
| 9435 + CHECK_MPI_OK(mp_exptmod(&mp_g,&mp_x,&mp_N,&mp_res2)); |
| 9436 + CHECK_MPI_OK(mp_mulmod(&mp_res2,&mp_k,&mp_N,&mp_res2)); |
| 9437 + CHECK_MPI_OK(mp_submod(&mp_B,&mp_res2,&mp_N,&mp_res2)); |
| 9438 + CHECK_MPI_OK(mp_mul(&mp_u, &mp_x, &mp_res1)); |
| 9439 + CHECK_MPI_OK(mp_add(&mp_res1,&mp_a,&mp_res1)); |
| 9440 + CHECK_MPI_OK(mp_exptmod(&mp_res2,&mp_res1,&mp_N,&mp_pms)); |
| 9441 + |
| 9442 + MPINT_TO_SECITEM(&mp_pms, pms, NULL); |
| 9443 + rv = SECSuccess; |
| 9444 +cleanup: |
| 9445 + PORT_Free(zero); |
| 9446 + SECITEM_FreeItem(it_u, PR_TRUE); |
| 9447 + SECITEM_FreeItem(it_k, PR_TRUE); |
| 9448 + SECITEM_FreeItem(it_x, PR_TRUE); |
| 9449 + SHA1_DestroyContext(ctx, PR_TRUE); |
| 9450 + mp_clear(&mp_N); |
| 9451 + mp_clear(&mp_g); |
| 9452 + mp_clear(&mp_a); |
| 9453 + mp_clear(&mp_A); |
| 9454 + mp_clear(&mp_B); |
| 9455 + mp_clear(&mp_k); |
| 9456 + mp_clear(&mp_u); |
| 9457 + mp_clear(&mp_x); |
| 9458 + mp_clear(&mp_pms); |
| 9459 + mp_clear(&mp_res1); |
| 9460 + mp_clear(&mp_res2); |
| 9461 + if (err) { |
| 9462 + MP_TO_SEC_ERROR(err); |
| 9463 + rv = SECFailure; |
| 9464 + } |
| 9465 + return rv; |
| 9466 +} |
| 9467 + |
| 9468 + |
| 9469 +/* SRP_NewServerKeyPair |
| 9470 + * creates a new srp key pair for the server |
| 9471 + * |
| 9472 + * k = SHA1(N | PAD(g)) |
| 9473 + * pubKey = k*v + g^prvKey % N |
| 9474 + */ |
| 9475 +SECStatus SRP_NewServerKeyPair(SRPPrivateKey **prvKey, SRPKeyPairParams *srp) { |
| 9476 + |
| 9477 + mp_int mp_N, mp_g, mp_pub, mp_prv, mp_k, mp_v, mp_res; |
| 9478 + PRArenaPool *arena; |
| 9479 + SRPPrivateKey *key; |
| 9480 + SECItem *it_k; |
| 9481 + unsigned char *zero; |
| 9482 + mp_err err = MP_OKAY; |
| 9483 + SECStatus rv = SECFailure; |
| 9484 + SHA1Context *ctx = SHA1_NewContext(); |
| 9485 + |
| 9486 + |
| 9487 + if (!srp || !prvKey) { |
| 9488 + PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| 9489 + return SECFailure; |
| 9490 + } |
| 9491 + arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); |
| 9492 + if (!arena) { |
| 9493 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9494 + return SECFailure; |
| 9495 + } |
| 9496 + key = (SRPPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SRPPrivateKey)); |
| 9497 + if (!key) { |
| 9498 + PORT_FreeArena(arena, PR_TRUE); |
| 9499 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9500 + return SECFailure; |
| 9501 + } |
| 9502 + key->arena = arena; |
| 9503 + |
| 9504 + /* prv=rand() */ |
| 9505 + SECITEM_AllocItem(arena, &key->prvKey, SRP_SECRET_KEY_LEN); |
| 9506 + rv = RNG_GenerateGlobalRandomBytes(key->prvKey.data, key->prvKey.len); |
| 9507 + |
| 9508 + if (rv != SECSuccess || !(&key->prvKey)) { |
| 9509 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9510 + PORT_FreeArena(arena, PR_TRUE); |
| 9511 + return SECFailure; |
| 9512 + } |
| 9513 + |
| 9514 + it_k = SECITEM_AllocItem(NULL, NULL, SHA1_LENGTH); |
| 9515 + zero = PORT_ZAlloc(srp->N.len); |
| 9516 + |
| 9517 + if (!zero || !it_k) { |
| 9518 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9519 + goto cleanup; |
| 9520 + } |
| 9521 + |
| 9522 + /* k = SHA1( N | PAD(g) ) */ |
| 9523 + SHA1_Begin(ctx); |
| 9524 + SHA1_Update(ctx, srp->N.data, srp->N.len); |
| 9525 + SHA1_Update(ctx, zero, srp->N.len - srp->g.len); |
| 9526 + SHA1_Update(ctx, srp->g.data, srp->g.len); |
| 9527 + SHA1_End(ctx, it_k->data, &it_k->len, SHA1_LENGTH); |
| 9528 + |
| 9529 + /* |
| 9530 + * create key pair |
| 9531 + */ |
| 9532 + CHECK_MPI_OK( mp_init(&mp_N) ); |
| 9533 + CHECK_MPI_OK( mp_init(&mp_g) ); |
| 9534 + CHECK_MPI_OK( mp_init(&mp_k) ); |
| 9535 + CHECK_MPI_OK( mp_init(&mp_v) ); |
| 9536 + CHECK_MPI_OK( mp_init(&mp_pub)); |
| 9537 + CHECK_MPI_OK( mp_init(&mp_prv)); |
| 9538 + CHECK_MPI_OK( mp_init(&mp_res)); |
| 9539 + SECITEM_TO_MPINT(*it_k, &mp_k); |
| 9540 + SECITEM_TO_MPINT(srp->N, &mp_N); |
| 9541 + SECITEM_TO_MPINT(srp->g, &mp_g); |
| 9542 + SECITEM_TO_MPINT(srp->secret, &mp_v); |
| 9543 + SECITEM_TO_MPINT(key->prvKey, &mp_prv); |
| 9544 + |
| 9545 + char *N_str; |
| 9546 + char *g_str; |
| 9547 + printf("X\n"); |
| 9548 + N_str = PORT_ZAlloc(mp_radix_size(&mp_N,16)); |
| 9549 + mp_toradix(&mp_N,N_str,16); |
| 9550 + printf("%s\n",N_str); |
| 9551 + g_str = PORT_ZAlloc(mp_radix_size(&mp_g,16)); |
| 9552 + mp_toradix(&mp_g,g_str,16); |
| 9553 + printf("%s\n",g_str); |
| 9554 + printf("X\n"); |
| 9555 + |
| 9556 + |
| 9557 + /* pub = k*v + g^prv % N */ |
| 9558 + CHECK_MPI_OK(mp_exptmod(&mp_g, &mp_prv, &mp_N, &mp_pub)); |
| 9559 + CHECK_MPI_OK(mp_mulmod(&mp_k, &mp_v, &mp_N, &mp_res)); |
| 9560 + CHECK_MPI_OK(mp_addmod(&mp_res, &mp_pub, &mp_N, &mp_pub)); |
| 9561 + |
| 9562 + MPINT_TO_SECITEM(&mp_pub, &key->pubKey, arena); |
| 9563 + CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->secret, &srp->secret)); |
| 9564 + *prvKey = key; |
| 9565 + |
| 9566 +cleanup: |
| 9567 + PORT_Free(zero); |
| 9568 + SECITEM_FreeItem(it_k,PR_TRUE); |
| 9569 + SHA1_DestroyContext(ctx, PR_TRUE); |
| 9570 + mp_clear(&mp_N); |
| 9571 + mp_clear(&mp_g); |
| 9572 + mp_clear(&mp_k); |
| 9573 + mp_clear(&mp_v); |
| 9574 + mp_clear(&mp_pub); |
| 9575 + mp_clear(&mp_prv); |
| 9576 + mp_clear(&mp_res); |
| 9577 + if (err) { |
| 9578 + PORT_FreeArena(arena, PR_TRUE); /* not zeroized!! */ |
| 9579 + MP_TO_SEC_ERROR(err); |
| 9580 + rv = SECFailure; |
| 9581 + } |
| 9582 + return rv; |
| 9583 +} |
| 9584 + |
| 9585 +/* SRP_NewClientKeyPair |
| 9586 + * creates a new srp key pair for the client |
| 9587 + * |
| 9588 + * prv = rand() |
| 9589 + * pub = g^prv % N, with prv at least 256bit random |
| 9590 + * prvKey->secret = srp->secret |
| 9591 + */ |
| 9592 + |
| 9593 +SECStatus SRP_NewClientKeyPair(SRPPrivateKey **prvKey, SRPKeyPairParams *srp) { |
| 9594 + |
| 9595 + |
| 9596 + SRPPrivateKey *key; |
| 9597 + PRArenaPool *arena; |
| 9598 + mp_int mp_N, mp_g, mp_prv, mp_pub; |
| 9599 + mp_err err = MP_OKAY; |
| 9600 + SECStatus rv = SECFailure; |
| 9601 + |
| 9602 + if (!srp || !prvKey) { |
| 9603 + PORT_SetError(SEC_ERROR_INVALID_ARGS); |
| 9604 + return SECFailure; |
| 9605 + } |
| 9606 + |
| 9607 + arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE); |
| 9608 + if (!arena) { |
| 9609 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9610 + return SECFailure; |
| 9611 + } |
| 9612 + |
| 9613 + key = (SRPPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SRPPrivateKey)); |
| 9614 + if (!key) { |
| 9615 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9616 + PORT_FreeArena(arena, PR_TRUE); |
| 9617 + return SECFailure; |
| 9618 + } |
| 9619 + key->arena = arena; |
| 9620 + |
| 9621 + /* prv=rand() */ |
| 9622 + SECITEM_AllocItem(arena, &key->prvKey, SRP_SECRET_KEY_LEN); |
| 9623 + rv = RNG_GenerateGlobalRandomBytes(key->prvKey.data, key->prvKey.len); |
| 9624 + |
| 9625 + if (rv != SECSuccess || !(&key->prvKey)) { |
| 9626 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 9627 + PORT_FreeArena(arena, PR_TRUE); |
| 9628 + return SECFailure; |
| 9629 + } |
| 9630 + |
| 9631 + /* pub = g^prv % N */ |
| 9632 + CHECK_MPI_OK( mp_init(&mp_N) ); |
| 9633 + CHECK_MPI_OK( mp_init(&mp_g) ); |
| 9634 + CHECK_MPI_OK( mp_init(&mp_pub)); |
| 9635 + CHECK_MPI_OK( mp_init(&mp_prv)); |
| 9636 + SECITEM_TO_MPINT(srp->N, &mp_N); |
| 9637 + SECITEM_TO_MPINT(srp->g, &mp_g); |
| 9638 + SECITEM_TO_MPINT(key->prvKey, &mp_prv); |
| 9639 + |
| 9640 + if (SECSuccess != check_srp_group(&mp_N, &mp_g)) |
| 9641 + goto cleanup; |
| 9642 + |
| 9643 + CHECK_MPI_OK( mp_exptmod(&mp_g, &mp_prv, &mp_N, &mp_pub) ); |
| 9644 + |
| 9645 + MPINT_TO_SECITEM(&mp_pub, &key->pubKey, key->arena); |
| 9646 + CHECK_SEC_OK( SECITEM_CopyItem(arena, &key->secret, &srp->secret) ); |
| 9647 + *prvKey = key; |
| 9648 + |
| 9649 +cleanup: |
| 9650 + mp_clear(&mp_g); |
| 9651 + mp_clear(&mp_N); |
| 9652 + mp_clear(&mp_pub); |
| 9653 + mp_clear(&mp_prv); |
| 9654 + if (err) { |
| 9655 + PORT_FreeArena(arena, PR_TRUE); /* not zeroized!! */ |
| 9656 + MP_TO_SEC_ERROR(err); |
| 9657 + rv = SECFailure; |
| 9658 + } |
| 9659 + return rv; |
| 9660 +} |
| 9661 + |
| 9662 diff --git a/net/third_party/nss/ssl/srp_groups.h b/net/third_party/nss/ssl/srp_
groups.h |
| 9663 new file mode 100644 |
| 9664 index 0000000..e327a0f |
| 9665 --- /dev/null |
| 9666 +++ b/net/third_party/nss/ssl/srp_groups.h |
| 9667 @@ -0,0 +1,58 @@ |
| 9668 +/* ***** BEGIN LICENSE BLOCK ***** |
| 9669 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 9670 + * |
| 9671 + * The contents of this file are subject to the Mozilla Public License Version |
| 9672 + * 1.1 (the "License"); you may not use this file except in compliance with |
| 9673 + * the License. You may obtain a copy of the License at |
| 9674 + * http://www.mozilla.org/MPL/ |
| 9675 + * |
| 9676 + * Software distributed under the License is distributed on an "AS IS" basis, |
| 9677 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| 9678 + * for the specific language governing rights and limitations under the |
| 9679 + * License. |
| 9680 + * |
| 9681 + * The Initial Developer of the Original Code is |
| 9682 + * Steffen Schulz - pepe (at) cbg.dyndns.org |
| 9683 + * |
| 9684 + * Portions created by the Initial Developer are Copyright (C) 2007 |
| 9685 + * the Initial Developer. All Rights Reserved. |
| 9686 + * |
| 9687 + * Contributor(s): |
| 9688 + * |
| 9689 + * Alternatively, the contents of this file may be used under the terms of |
| 9690 + * either the GNU General Public License Version 2 or later (the "GPL"), or |
| 9691 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| 9692 + * in which case the provisions of the GPL or the LGPL are applicable instead |
| 9693 + * of those above. If you wish to allow use of your version of this file only |
| 9694 + * under the terms of either the GPL or the LGPL, and not to allow others to |
| 9695 + * use your version of this file under the terms of the MPL, indicate your |
| 9696 + * decision by deleting the provisions above and replace them with the notice |
| 9697 + * and other provisions required by the GPL or the LGPL. If you do not delete |
| 9698 + * the provisions above, a recipient may use your version of this file under |
| 9699 + * the terms of any one of the MPL, the GPL or the LGPL. |
| 9700 + * |
| 9701 + * ***** END LICENSE BLOCK ***** */ |
| 9702 + |
| 9703 +/* number of known groups */ |
| 9704 +#define SRP_KNOWN_GROUPS 7 |
| 9705 + |
| 9706 +/* Whitelist of known-good group parameters, taken from RFC 5054. The client |
| 9707 + * checks supplied params against this whitelist. There is currently no support |
| 9708 + * for application specified group parameters. |
| 9709 + */ |
| 9710 + |
| 9711 +struct srp_group { |
| 9712 + char *modulus; |
| 9713 + char *generator; |
| 9714 +}; |
| 9715 + |
| 9716 +const struct srp_group known_srp_groups[SRP_KNOWN_GROUPS] = { |
| 9717 + { "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF74
96EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD
69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE
8376435B9FC61D2FC0EB06E3", "2"}, |
| 9718 + { "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F55
6E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8
B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF0195
39349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9
B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB", "2"}, |
| 9719 + { "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CB
B4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF609517
9A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041
D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E6
88F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E73
03CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D
525F54759B65E372FCD68EF20FA7111F9E4AFF73", "2"}, |
| 9720 + { "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA6
3B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576
625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651
ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356
208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C
180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D22618
98FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA7157
5D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06
D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA0
74E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", "5"}, |
| 9721 + { "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA6
3B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576
625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651
ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356
208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C
180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D22618
98FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA7157
5D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06
D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA0
74E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C32718
6AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C5947
4E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127
D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", "5",}
, |
| 9722 + { "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA6
3B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576
625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651
ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356
208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C
180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D22618
98FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA7157
5D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06
D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA0
74E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C32718
6AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C5947
4E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127
D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2
602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0
865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401
378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031
900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7E
BF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1
A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E
6DCC4024FFFFFFFFFFFFFFFF", "5"}, |
| 9723 + { "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA6
3B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576
625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651
ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356
208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C
180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D22618
98FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA7157
5D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06
D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA0
74E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C32718
6AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C5947
4E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127
D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2
602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0
865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401
378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031
900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7E
BF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1
A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E
6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF
8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BE
FC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7F
A2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899
A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4
EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2
765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF", "13"} |
| 9724 +}; |
| 9725 + |
| 9726 diff --git a/net/third_party/nss/ssl/ssl.def b/net/third_party/nss/ssl/ssl.def |
| 9727 index 76417d0..0af96ba 100644 |
| 9728 --- a/net/third_party/nss/ssl/ssl.def |
| 9729 +++ b/net/third_party/nss/ssl/ssl.def |
| 9730 @@ -136,6 +136,10 @@ SSL_ReHandshakeWithTimeout; |
| 9731 ;+NSS_3.11.8 { # NSS 3.11.8 release |
| 9732 ;+ global: |
| 9733 SSL_CanBypass; |
| 9734 + |
| 9735 +SSL_SetUserLogin; |
| 9736 +SSL_UserPasswdHook; |
| 9737 +SSL_GetSRPParamsHook; |
| 9738 ;+ local: |
| 9739 ;+*; |
| 9740 ;+}; |
| 9741 diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h |
| 9742 index 21d7c8d..8a8d53f 100644 |
| 9743 --- a/net/third_party/nss/ssl/ssl.h |
| 9744 +++ b/net/third_party/nss/ssl/ssl.h |
| 9745 @@ -437,6 +437,41 @@ SSL_IMPORT PRFileDesc *SSL_ReconfigFD(PRFileDesc *model, PR
FileDesc *fd); |
| 9746 */ |
| 9747 SSL_IMPORT SECStatus SSL_SetPKCS11PinArg(PRFileDesc *fd, void *a); |
| 9748 |
| 9749 + |
| 9750 +/* |
| 9751 + * Set the client side user name and password non-interactively. |
| 9752 + */ |
| 9753 +SSL_IMPORT SECStatus SSL_SetUserLogin(PRFileDesc *fd, char *u, char *p); |
| 9754 + |
| 9755 +/* |
| 9756 + * This sets the client side callback for SSL to retrieve the user password. |
| 9757 + * fd - the file descriptor for the connection in question |
| 9758 + * func - callback function pointer |
| 9759 + * pw - user password |
| 9760 + */ |
| 9761 + |
| 9762 +typedef SECStatus (PR_CALLBACK *SSLUserPasswdCB)(PRFileDesc *fd, |
| 9763 + SECItem *pw, void *arg); |
| 9764 + |
| 9765 +SSL_IMPORT SECStatus SSL_UserPasswdHook(PRFileDesc *fd, SSLUserPasswdCB func, |
| 9766 + void *arg); |
| 9767 + |
| 9768 +/* |
| 9769 + * This sets the server side callback function for SSL to retrieve the SRP |
| 9770 + * authentication parameters associated with a specific user login. |
| 9771 + * fd - the file descriptor of the connection |
| 9772 + * func - pointer to the callback function |
| 9773 + * user - username to lookup in app database |
| 9774 + * srp - SRP auth paramters supplied to SSL by app |
| 9775 + */ |
| 9776 + |
| 9777 +typedef SECStatus (PR_CALLBACK *SSLGetSRPParamsCB)(PRFileDesc *fd, |
| 9778 + SECKEYSRPParams *srp, |
| 9779 + void *arg); |
| 9780 + |
| 9781 +SSL_IMPORT SECStatus SSL_GetSRPParamsHook(PRFileDesc *fd, |
| 9782 + SSLGetSRPParamsCB func, void *arg); |
| 9783 + |
| 9784 /* |
| 9785 ** This is a callback for dealing with server certs that are not authenticated |
| 9786 ** by the client. The client app can decide that it actually likes the |
| 9787 diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con
.c |
| 9788 index f5c0880..8f1f9e4 100644 |
| 9789 --- a/net/third_party/nss/ssl/ssl3con.c |
| 9790 +++ b/net/third_party/nss/ssl/ssl3con.c |
| 9791 @@ -118,6 +118,9 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEME
NTED] = { |
| 9792 #endif /* NSS_ENABLE_ECC */ |
| 9793 { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_
FALSE}, |
| 9794 { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9795 + { TLS_SRP_SHA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9796 + { TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9797 + { TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9798 |
| 9799 #ifdef NSS_ENABLE_ECC |
| 9800 { TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9801 @@ -141,11 +144,15 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLE
MENTED] = { |
| 9802 { SSL_RSA_WITH_RC4_128_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
| 9803 { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9804 { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9805 + { TLS_SRP_SHA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9806 + { TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9807 + { TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9808 |
| 9809 #ifdef NSS_ENABLE_ECC |
| 9810 { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9811 { TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9812 #endif /* NSS_ENABLE_ECC */ |
| 9813 + { TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9814 { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9815 { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9816 #ifdef NSS_ENABLE_ECC |
| 9817 @@ -154,6 +161,8 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEME
NTED] = { |
| 9818 #endif /* NSS_ENABLE_ECC */ |
| 9819 { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
| 9820 { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
| 9821 + { TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9822 + { TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9823 |
| 9824 |
| 9825 { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
| 9826 @@ -283,6 +292,9 @@ static const ssl3KEADef kea_defs[] = |
| 9827 {kea_dh_anon, kt_dh, sign_null, PR_FALSE, 0, PR_FALSE}, |
| 9828 {kea_dh_anon_export, kt_dh, sign_null, PR_TRUE, 512, PR_FALSE}, |
| 9829 {kea_rsa_fips, kt_rsa, sign_rsa, PR_FALSE, 0, PR_TRUE }, |
| 9830 + {kea_srp, kt_srp, sign_null, PR_FALSE, 0, PR_FALSE}, |
| 9831 + {kea_srp_rsa, kt_srp, sign_rsa, PR_FALSE, 0, PR_FALSE}, |
| 9832 + {kea_srp_dss, kt_srp, sign_dsa, PR_FALSE, 0, PR_FALSE}, |
| 9833 #ifdef NSS_ENABLE_ECC |
| 9834 {kea_ecdh_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE}, |
| 9835 {kea_ecdhe_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE}, |
| 9836 @@ -344,6 +356,21 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] = |
| 9837 |
| 9838 |
| 9839 /* New TLS cipher suites */ |
| 9840 + {TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, kea_srp}, |
| 9841 + {TLS_SRP_SHA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_srp}, |
| 9842 + {TLS_SRP_SHA_WITH_AES_256_CBC_SHA, cipher_aes_256, mac_sha, kea_srp}, |
| 9843 + {TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, |
| 9844 + cipher_3des, mac_sha, kea_srp_rsa}, |
| 9845 + {TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, |
| 9846 + cipher_3des, mac_sha, kea_srp_dss}, |
| 9847 + {TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, |
| 9848 + cipher_aes_128, mac_sha, kea_srp_rsa}, |
| 9849 + {TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, |
| 9850 + cipher_aes_128, mac_sha, kea_srp_dss}, |
| 9851 + {TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, |
| 9852 + cipher_aes_256, mac_sha, kea_srp_rsa}, |
| 9853 + {TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, |
| 9854 + cipher_aes_256, mac_sha, kea_srp_dss}, |
| 9855 {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_rsa
}, |
| 9856 {TLS_DHE_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe
_dss}, |
| 9857 {TLS_DHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_dhe
_rsa}, |
| 9858 @@ -420,7 +447,8 @@ static const CK_MECHANISM_TYPE kea_alg_defs[] = { |
| 9859 CKM_RSA_PKCS, |
| 9860 CKM_DH_PKCS_DERIVE, |
| 9861 CKM_KEA_KEY_DERIVE, |
| 9862 - CKM_ECDH1_DERIVE |
| 9863 + CKM_ECDH1_DERIVE, |
| 9864 + CKM_NSS_SRP_DERIVE |
| 9865 }; |
| 9866 |
| 9867 typedef struct SSLCipher2MechStr { |
| 9868 @@ -695,12 +723,27 @@ ssl3_config_match_init(sslSocket *ss) |
| 9869 } |
| 9870 #endif /* NSS_ENABLE_ECC */ |
| 9871 |
| 9872 + /* XXX this should be merged with switch(kea) from above */ |
| 9873 + switch (cipher_def->key_exchange_alg) { |
| 9874 + case kea_srp_rsa: |
| 9875 + svrAuth = ss->serverCerts + kt_rsa; |
| 9876 + break; |
| 9877 + case kea_srp_dss: |
| 9878 + svrAuth = ss->serverCerts + kt_null; /* don't ask me..*/ |
| 9879 + break; |
| 9880 + default: |
| 9881 + svrAuth = ss->serverCerts + exchKeyType; |
| 9882 + break; |
| 9883 + } |
| 9884 + |
| 9885 + |
| 9886 /* Mark the suites that are backed by real tokens, certs and keys */ |
| 9887 suite->isPresent = (PRBool) |
| 9888 (((exchKeyType == kt_null) || |
| 9889 ((!isServer || (svrAuth->serverKeyPair && |
| 9890 svrAuth->SERVERKEY && |
| 9891 - svrAuth->serverCertChain)) && |
| 9892 + svrAuth->serverCertChain) || |
| 9893 + cipher_def->key_exchange_alg == kea_srp) && |
| 9894 PK11_TokenExists(kea_alg_defs[exchKeyType]))) && |
| 9895 ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech))); |
| 9896 if (suite->isPresent) |
| 9897 @@ -1080,6 +1123,57 @@ ssl3_ComputeExportRSAKeyHash(SECItem modulus, SECItem pub
licExponent, |
| 9898 return rv; |
| 9899 } |
| 9900 |
| 9901 +/* Caller must set hiLevel error code. |
| 9902 + * Called from ssl3_SendSRPServerKeyExchange */ |
| 9903 +static SECStatus |
| 9904 +ssl3_ComputeSRPKeyHash(SECItem *N, SECItem *g, SECItem *s, SECItem *B, |
| 9905 + SSL3Random *client_rand, SSL3Random *server_rand, |
| 9906 + SSL3Hashes *hashes, PRBool bypassPKCS11) |
| 9907 +{ |
| 9908 + PRUint8 * hashBuf; |
| 9909 + PRUint8 * pBuf; |
| 9910 + SECStatus rv = SECFailure; |
| 9911 + unsigned int bufLen; |
| 9912 + |
| 9913 + bufLen = 2*SSL3_RANDOM_LENGTH + N->len + 2 + g->len + 2 |
| 9914 + + s->len + 1 + B->len + 2; |
| 9915 + |
| 9916 + hashBuf = PORT_Alloc(bufLen); |
| 9917 + if (!hashBuf) { |
| 9918 + return SECFailure; |
| 9919 + } |
| 9920 + |
| 9921 + memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); |
| 9922 + pBuf = hashBuf + SSL3_RANDOM_LENGTH; |
| 9923 + memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); |
| 9924 + pBuf += SSL3_RANDOM_LENGTH; |
| 9925 + pBuf[0] = (PRUint8)(N->len >> 8); |
| 9926 + pBuf[1] = (PRUint8)(N->len); |
| 9927 + pBuf+=2; |
| 9928 + memcpy(pBuf, N->data, N->len); |
| 9929 + pBuf += N->len; |
| 9930 + pBuf[0] = (PRUint8)(g->len >> 8); |
| 9931 + pBuf[1] = (PRUint8)(g->len); |
| 9932 + pBuf+=2; |
| 9933 + memcpy(pBuf, g->data, g->len); |
| 9934 + pBuf += g->len; |
| 9935 + pBuf[0] = (PRUint8)(s->len); |
| 9936 + pBuf+=1; |
| 9937 + memcpy(pBuf, s->data, s->len); |
| 9938 + pBuf += s->len; |
| 9939 + pBuf[0] = (PRUint8)(B->len >> 8); |
| 9940 + pBuf[1] = (PRUint8)(B->len); |
| 9941 + pBuf+=2; |
| 9942 + memcpy(pBuf, B->data, B->len); |
| 9943 + pBuf += B->len; |
| 9944 + |
| 9945 + rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11); |
| 9946 + |
| 9947 + if (hashBuf) |
| 9948 + PORT_Free(hashBuf); |
| 9949 + return rv; |
| 9950 +} |
| 9951 + |
| 9952 /* Caller must set hiLevel error code. */ |
| 9953 /* Called from ssl3_HandleServerKeyExchange. */ |
| 9954 static SECStatus |
| 9955 @@ -2663,6 +2757,8 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) |
| 9956 error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT; break; |
| 9957 case bad_certificate_hash_value: |
| 9958 error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT; break; |
| 9959 + case unknown_psk_identity: |
| 9960 + error = SSL_ERROR_UNKNOWN_PSK_IDENTITY_ALERT; break; |
| 9961 default: error = SSL_ERROR_RX_UNKNOWN_ALERT; break; |
| 9962 } |
| 9963 if (level == alert_fatal) { |
| 9964 @@ -2828,7 +2924,8 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) |
| 9965 * data into a 48-byte value. |
| 9966 */ |
| 9967 PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) || |
| 9968 - (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh)); |
| 9969 + (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh) || |
| 9970 + (ss->ssl3.hs.kea_def->exchKeyType == kt_srp)); |
| 9971 SECStatus rv = SECFailure; |
| 9972 CK_MECHANISM_TYPE master_derive; |
| 9973 CK_MECHANISM_TYPE key_derive; |
| 9974 @@ -4733,8 +4830,242 @@ loser: |
| 9975 return rv; |
| 9976 } |
| 9977 |
| 9978 +/* Read srp values from datastream and verify the signature |
| 9979 + * if requiried by cipher. Save parameters to ss->sec.peerKey. |
| 9980 + * |
| 9981 + * called from ssl3_HandleServerKeyExchange |
| 9982 + */ |
| 9983 +static SECStatus |
| 9984 +ssl3_HandleSRPServerKeyExchange(sslSocket *ss, SSL3Opaque *b, |
| 9985 + PRUint32 length) { |
| 9986 + |
| 9987 + SECItem signature = {siBuffer, NULL, 0}; |
| 9988 + PRArenaPool *arena = NULL; |
| 9989 + SECKEYPublicKey *peerKey = NULL; |
| 9990 + SECStatus rv; |
| 9991 + SSL3Hashes hashes; |
| 9992 + SECItem srp_N, srp_g, srp_s, srp_ppub; |
| 9993 + int errCode; |
| 9994 + |
| 9995 + rv = ssl3_ConsumeHandshakeVariable(ss, &srp_N, 2, &b, &length); |
| 9996 + if (rv != SECSuccess) { |
| 9997 + goto loser; /* malformed. */ |
| 9998 + } |
| 9999 + rv = ssl3_ConsumeHandshakeVariable(ss, &srp_g, 2, &b, &length); |
| 10000 + if (rv != SECSuccess) { |
| 10001 + goto loser; /* malformed. */ |
| 10002 + } |
| 10003 + rv = ssl3_ConsumeHandshakeVariable(ss, &srp_s, 1, &b, &length); |
| 10004 + if (rv != SECSuccess) { |
| 10005 + goto loser; /* malformed. */ |
| 10006 + } |
| 10007 + rv = ssl3_ConsumeHandshakeVariable(ss, &srp_ppub, 2, &b, &length); |
| 10008 + if (rv != SECSuccess) { |
| 10009 + goto loser; /* malformed. */ |
| 10010 + } |
| 10011 + |
| 10012 + if (ss->ssl3.hs.kea_def->kea != kea_srp) { /* there MUST be a signature */ |
| 10013 + rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); |
| 10014 + if (rv != SECSuccess) { |
| 10015 + goto loser; /* malformed. */ |
| 10016 + } |
| 10017 + rv = ssl3_ComputeSRPKeyHash(&srp_N, &srp_g, &srp_s, &srp_ppub, |
| 10018 + &ss->ssl3.hs.client_random, |
| 10019 + &ss->ssl3.hs.server_random, |
| 10020 + &hashes, ss->opt.bypassPKCS11); |
| 10021 + if (rv != SECSuccess) { |
| 10022 + errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
); |
| 10023 + goto alert_loser; |
| 10024 + } |
| 10025 + rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature, |
| 10026 + PR_TRUE, ss->pkcs11P
inArg); |
| 10027 + if (rv != SECSuccess) { |
| 10028 + errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
); |
| 10029 + goto alert_loser; |
| 10030 + } |
| 10031 + } |
| 10032 + |
| 10033 + /* all ok, save and return */ |
| 10034 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 10035 + if (arena == NULL) { |
| 10036 + return SECFailure; |
| 10037 + } |
| 10038 + ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); |
| 10039 + if (peerKey == NULL) { |
| 10040 + return SECFailure; |
| 10041 + } |
| 10042 + peerKey->arena = arena; |
| 10043 + peerKey->keyType = srpKey; |
| 10044 + peerKey->pkcs11Slot = NULL; |
| 10045 + peerKey->pkcs11ID = CK_INVALID_HANDLE; |
| 10046 + |
| 10047 + if (SECITEM_CopyItem(arena, &peerKey->u.srp.N, &srp_N) || |
| 10048 + SECITEM_CopyItem(arena, &peerKey->u.srp.g, &srp_g) || |
| 10049 + SECITEM_CopyItem(arena, &peerKey->u.srp.s, &srp_s) || |
| 10050 + SECITEM_CopyItem(arena, &peerKey->u.srp.ppub, &srp_ppub)) { |
| 10051 + return SECFailure; |
| 10052 + } |
| 10053 + return SECSuccess; |
| 10054 + |
| 10055 +alert_loser: |
| 10056 + (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); |
| 10057 +loser: |
| 10058 + PORT_SetError(errCode); |
| 10059 + return SECFailure; |
| 10060 +} |
| 10061 + |
| 10062 +/* Calculate ClientKeyExchange and Pre-Master-Secret via SRP_GenKeys(), |
| 10063 + * then send ClientKeyExchange and derive SSL master key |
| 10064 + * |
| 10065 + * called from ssl3_SendClientKeyExchange() |
| 10066 + */ |
| 10067 +static SECStatus |
| 10068 +ssl3_SendSRPClientKeyExchange(sslSocket *ss, SECKEYPublicKey * pubKey) { |
| 10069 + |
| 10070 + SECKEYSRPParams *srpParam; |
| 10071 + SECStatus rv; |
| 10072 + |
| 10073 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
| 10074 + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
| 10075 + |
| 10076 + srpParam = PORT_ZAlloc(sizeof(SECKEYSRPParams)); |
| 10077 + if (!srpParam) { |
| 10078 + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
| 10079 + goto loser; |
| 10080 + } |
| 10081 + |
| 10082 + /* PW-Callback overrides SSL_SetUserLogin. If both fail to |
| 10083 + * provide a password, the token must know it or fail. */ |
| 10084 + if (ss->getUserPasswd) { |
| 10085 + if (!ss->sec.userPasswd) |
| 10086 + ss->sec.userPasswd = SECITEM_AllocItem(NULL,NULL,0); |
| 10087 + SECITEM_FreeItem(ss->sec.userPasswd, PR_FALSE); |
| 10088 + ss->getUserPasswd(ss->fd, ss->sec.userPasswd, ss->getUserPasswdArg); |
| 10089 + } |
| 10090 + if (ss->sec.userPasswd) { |
| 10091 + srpParam->secret.data = ss->sec.userPasswd->data; |
| 10092 + srpParam->secret.len = ss->sec.userPasswd->len; |
| 10093 + ss->sec.userPasswd = NULL; |
| 10094 + } |
| 10095 |
| 10096 + /* calculate client key pair and PMS, then send key exchange data */ |
| 10097 + if (ss->opt.bypassPKCS11) { |
| 10098 + SECItem pms = {0, NULL, 0}; |
| 10099 + SRPPrivateKey *prvKey; |
| 10100 + SRPKeyPairParams keyPairParam; |
| 10101 + keyPairParam.N.data = pubKey->u.srp.N.data; |
| 10102 + keyPairParam.N.len = pubKey->u.srp.N.len; |
| 10103 + keyPairParam.g.data = pubKey->u.srp.g.data; |
| 10104 + keyPairParam.g.len = pubKey->u.srp.g.len; |
| 10105 + keyPairParam.secret.data = srpParam->secret.data; |
| 10106 + keyPairParam.secret.len = srpParam->secret.len; |
| 10107 + |
| 10108 + rv = SRP_NewClientKeyPair(&prvKey, &keyPairParam); |
| 10109 + if (rv != SECSuccess) goto loser; /* err set by SRP_ClientDerive */ |
| 10110 + |
| 10111 + SRPDeriveParams deriveParam; |
| 10112 + deriveParam.N.data = pubKey->u.srp.N.data; |
| 10113 + deriveParam.N.len = pubKey->u.srp.N.len; |
| 10114 + deriveParam.g.data = pubKey->u.srp.g.data; |
| 10115 + deriveParam.g.len = pubKey->u.srp.g.len; |
| 10116 + deriveParam.s.data = pubKey->u.srp.s.data; |
| 10117 + deriveParam.s.len = pubKey->u.srp.s.len; |
| 10118 + deriveParam.u.data = ss->sec.userName->data; |
| 10119 + deriveParam.u.len = ss->sec.userName->len; |
| 10120 + deriveParam.ppub.data= pubKey->u.srp.ppub.data; |
| 10121 + deriveParam.ppub.len = pubKey->u.srp.ppub.len; |
| 10122 + |
| 10123 + |
| 10124 + if (SECSuccess != SRP_ClientDerive(prvKey, &deriveParam, &pms)) { |
| 10125 + goto derive_fail; |
| 10126 + } |
| 10127 + |
| 10128 + /* client key exchange data */ |
| 10129 + rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, |
| 10130 + prvKey->pubKey.len + 2); |
| 10131 + if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* *
/ |
| 10132 + rv = ssl3_AppendHandshakeVariable(ss, prvKey->pubKey.data, |
| 10133 + prvKey->pubKey.len, 2); |
| 10134 + if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* *
/ |
| 10135 + |
| 10136 + /* init pending cipher spec*/ |
| 10137 + rv = ssl3_MasterKeyDeriveBypass(ss->ssl3.pwSpec, |
| 10138 + (unsigned char *)&ss->ssl3.hs.client_random, |
| 10139 + (unsigned char *)&ss->ssl3.hs.server_random, |
| 10140 + &pms, PR_TRUE, PR_FALSE); |
| 10141 + if (rv != SECSuccess) { |
| 10142 + ss->ssl3.pwSpec->msItem.data = ss->ssl3.pwSpec->raw_master_secret; |
| 10143 + ss->ssl3.pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; |
| 10144 + PK11_GenerateRandom(ss->ssl3.pwSpec->msItem.data, |
| 10145 + SSL3_MASTER_SECRET_LENGTH); |
| 10146 + } |
| 10147 + rv = ssl3_InitPendingCipherSpec(ss, NULL); |
| 10148 + |
| 10149 + SECITEM_FreeItem(&pms, PR_FALSE); |
| 10150 + PORT_FreeArena(prvKey->arena, PR_TRUE); |
| 10151 + } else { /* PK11 path */ |
| 10152 + PK11SymKey *pms = NULL; |
| 10153 + SECKEYPrivateKey *prvKey = NULL; |
| 10154 + SECKEYPublicKey *newPub = NULL; |
| 10155 + |
| 10156 + srpParam->N.data = pubKey->u.srp.N.data; |
| 10157 + srpParam->N.len = pubKey->u.srp.N.len; |
| 10158 + srpParam->g.data = pubKey->u.srp.g.data; |
| 10159 + srpParam->g.len = pubKey->u.srp.g.len; |
| 10160 + srpParam->s.data = pubKey->u.srp.s.data; |
| 10161 + srpParam->s.len = pubKey->u.srp.s.len; |
| 10162 + srpParam->u.data = ss->sec.userName->data; |
| 10163 + srpParam->u.len = ss->sec.userName->len; |
| 10164 + |
| 10165 + /* The token handles (missing) info supplied in srpParam |
| 10166 + * The template not actually involved in key generation, |
| 10167 + * but it's important in the server key exchange */ |
| 10168 + |
| 10169 + prvKey = SECKEY_CreateSRPPrivateKey(srpParam, &newPub, PR_FALSE, NULL); |
| 10170 + if (!prvKey) { |
| 10171 + ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); |
| 10172 + rv = SECFailure; |
| 10173 + goto loser; |
| 10174 + } |
| 10175 + SECITEM_CopyItem(newPub->arena, &newPub->u.srp.ppub, &pubKey->u.srp.ppu
b); |
| 10176 + |
| 10177 + /* Now all data is in newPub and prvKey, compute pms with them */ |
| 10178 + pms = PK11_PubDerive(prvKey, newPub, PR_FALSE, NULL, NULL, |
| 10179 + CKM_NSS_SRP_DERIVE, CKM_TLS_MASTER_KEY_DERIVE, CKF_D
ERIVE, 0, NULL); |
| 10180 |
| 10181 + if (!pms) { |
| 10182 + goto derive_fail; |
| 10183 + } |
| 10184 + |
| 10185 + /* init pending cipher spec*/ |
| 10186 + rv = ssl3_InitPendingCipherSpec(ss, pms); |
| 10187 + |
| 10188 + |
| 10189 + /* client key exchange data */ |
| 10190 + rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, |
| 10191 + newPub->u.srp.pub.len + 2); |
| 10192 + if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* *
/ |
| 10193 + rv = ssl3_AppendHandshakeVariable(ss, newPub->u.srp.pub.data, |
| 10194 + newPub->u.srp.pub.len, 2); |
| 10195 + if (rv != SECSuccess) goto loser; /* err set by ssl3_AppendHandshake* *
/ |
| 10196 + |
| 10197 + if (pms) PK11_FreeSymKey(pms); |
| 10198 + SECKEY_DestroyPublicKey(newPub); |
| 10199 + } /* end of PK11 path */ |
| 10200 + |
| 10201 +loser: |
| 10202 + SECITEM_FreeItem(ss->sec.userName, PR_TRUE); |
| 10203 + SECITEM_ZfreeItem(ss->sec.userPasswd, PR_TRUE); |
| 10204 + PORT_Free(srpParam); |
| 10205 + /* caller frees pubKey */ |
| 10206 + return rv; |
| 10207 +derive_fail: |
| 10208 + if (PORT_GetError() == SEC_ERROR_SRP_UNSUPPORTED_GROUP) |
| 10209 + SSL3_SendAlert(ss, alert_fatal, insufficient_security); |
| 10210 + if (PORT_GetError() == SEC_ERROR_SRP_ILLEGAL_PARAMETER) |
| 10211 + SSL3_SendAlert(ss, alert_fatal, illegal_parameter); |
| 10212 + return SECFailure; |
| 10213 +} |
| 10214 |
| 10215 |
| 10216 /* Called from ssl3_HandleServerHelloDone(). */ |
| 10217 @@ -4794,7 +5125,9 @@ ssl3_SendClientKeyExchange(sslSocket *ss) |
| 10218 rv = ssl3_SendECDHClientKeyExchange(ss, serverKey); |
| 10219 break; |
| 10220 #endif /* NSS_ENABLE_ECC */ |
| 10221 - |
| 10222 + case kt_srp: |
| 10223 + rv = ssl3_SendSRPClientKeyExchange(ss, serverKey); |
| 10224 + break; |
| 10225 default: |
| 10226 /* got an unknown or unsupported Key Exchange Algorithm. */ |
| 10227 SEND_ALERT |
| 10228 @@ -5284,7 +5617,8 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b,
PRUint32 length) |
| 10229 desc = unexpected_message; |
| 10230 goto alert_loser; |
| 10231 } |
| 10232 - if (ss->sec.peerCert == NULL) { |
| 10233 + if (ss->sec.peerCert == NULL && |
| 10234 + ss->ssl3.hs.suite_def->key_exchange_alg != kea_srp) { |
| 10235 errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH; |
| 10236 desc = unexpected_message; |
| 10237 goto alert_loser; |
| 10238 @@ -5473,6 +5807,13 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b
, PRUint32 length) |
| 10239 rv = ssl3_HandleECDHServerKeyExchange(ss, b, length); |
| 10240 return rv; |
| 10241 #endif /* NSS_ENABLE_ECC */ |
| 10242 + case kt_srp: |
| 10243 + rv = ssl3_HandleSRPServerKeyExchange(ss, b, length); |
| 10244 + if (rv != SECSuccess) { |
| 10245 + errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
); |
| 10246 + goto alert_loser; |
| 10247 + } |
| 10248 + return rv; |
| 10249 |
| 10250 default: |
| 10251 desc = handshake_failure; |
| 10252 @@ -6034,16 +6375,20 @@ ssl3_SendServerHelloSequence(sslSocket *ss) |
| 10253 if (rv != SECSuccess) { |
| 10254 return rv; /* err code is set. */ |
| 10255 } |
| 10256 - rv = ssl3_SendCertificate(ss); |
| 10257 - if (rv != SECSuccess) { |
| 10258 - return rv; /* error code is set. */ |
| 10259 - } |
| 10260 /* We have to do this after the call to ssl3_SendServerHello, |
| 10261 * because kea_def is set up by ssl3_SendServerHello(). |
| 10262 */ |
| 10263 kea_def = ss->ssl3.hs.kea_def; |
| 10264 ss->ssl3.hs.usedStepDownKey = PR_FALSE; |
| 10265 |
| 10266 + |
| 10267 + if (kea_def->kea != kea_srp) { /* SRP auth only */ |
| 10268 + rv = ssl3_SendCertificate(ss); |
| 10269 + if (rv != SECSuccess) { |
| 10270 + return rv; /* error code is set. */ |
| 10271 + } |
| 10272 + } |
| 10273 + |
| 10274 if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) { |
| 10275 /* see if we can legally use the key in the cert. */ |
| 10276 int keyLen; /* bytes */ |
| 10277 @@ -6075,6 +6420,11 @@ ssl3_SendServerHelloSequence(sslSocket *ss) |
| 10278 return rv; /* err code was set. */ |
| 10279 } |
| 10280 #endif /* NSS_ENABLE_ECC */ |
| 10281 + } else if ( kea_def->exchKeyType == kt_srp ) { |
| 10282 + rv = ssl3_SendServerKeyExchange(ss); |
| 10283 + if (rv != SECSuccess) { |
| 10284 + return rv; /* err code was set. */ |
| 10285 + } |
| 10286 } |
| 10287 |
| 10288 if (ss->opt.requestCertificate) { |
| 10289 @@ -7099,6 +7449,196 @@ ssl3_SendServerHello(sslSocket *ss) |
| 10290 return SECSuccess; |
| 10291 } |
| 10292 |
| 10293 +/* ssl3_SendSRPServerKeyExchange() |
| 10294 + * called by ssl3_SendServerKeyExchange() |
| 10295 + * |
| 10296 + * - make sure we got a userid in the srp client hello extension |
| 10297 + * - retrieve verifier and parameters for the user via callback func |
| 10298 + * - if user nonexistant, CB makes something up if it wants to |
| 10299 + * - continue by creating and sending the SRP key exchange data: |
| 10300 + * |
| 10301 + * N, g, s, v = <read from password file> |
| 10302 + * b = random() |
| 10303 + * k = SHA1(N | PAD(g)) |
| 10304 + * B = k*v + g^b % N |
| 10305 + * send (N,g,s,B) |
| 10306 + * |
| 10307 + * save values b,v,N for calculation of pms in ssl3_HandleSRPClientKeyExchange |
| 10308 + */ |
| 10309 + |
| 10310 +SECStatus |
| 10311 +ssl3_SendSRPServerKeyExchange(sslSocket *ss) { |
| 10312 + |
| 10313 + int bytes = 0; |
| 10314 + const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def; |
| 10315 + SECItem signed_hash = {siBuffer, NULL, 0}; |
| 10316 + SECStatus rv = SECFailure; |
| 10317 + SECKEYSRPPublicKey *srp = NULL; |
| 10318 + SECKEYPublicKey *pubKey = NULL; |
| 10319 + SECKEYPrivateKey *prvKey = NULL; |
| 10320 + SECKEYSRPParams *srpParams; |
| 10321 + SSL3Hashes hashes; |
| 10322 + |
| 10323 + /* send error if no userid was supplied in Client Hello */ |
| 10324 + if (!ss->sec.userName || !ss->sec.userName->data) |
| 10325 + goto unknown_id; |
| 10326 + |
| 10327 + /* Ask application for SRP parameters for specified username. |
| 10328 + * Information provided via callback overrides data set on token. |
| 10329 + * If no params provided, the token must supply them or fail. |
| 10330 + * Callback may fail for nonexistant user. |
| 10331 + */ |
| 10332 + |
| 10333 + srpParams = PORT_ZAlloc(sizeof(SECKEYSRPParams)); |
| 10334 + if (!srpParams) goto no_memory; |
| 10335 + |
| 10336 + srpParams->u.data = ss->sec.userName->data; |
| 10337 + srpParams->u.len = ss->sec.userName->len; |
| 10338 + |
| 10339 + if (ss->getSRPParams) { |
| 10340 + rv = ss->getSRPParams(ss->fd, srpParams, ss->getSRPParamsArg); |
| 10341 + if (rv != SECSuccess) { |
| 10342 + SECITEM_FreeItem(&srpParams->N, PR_FALSE); |
| 10343 + SECITEM_FreeItem(&srpParams->g, PR_FALSE); |
| 10344 + SECITEM_FreeItem(&srpParams->s, PR_FALSE); |
| 10345 + SECITEM_ZfreeItem(&srpParams->secret, PR_FALSE); |
| 10346 + PORT_Free(srpParams); |
| 10347 + goto unknown_id; |
| 10348 + } |
| 10349 + } |
| 10350 + |
| 10351 + /* create SRP server key pair */ |
| 10352 + if (ss->opt.bypassPKCS11) { |
| 10353 + /* srpParams, keyPairParams are temporary. pubKey and prvKey have |
| 10354 + * own arenas and are saved for ssl3_HandleSRPClientKeyExchange */ |
| 10355 + SRPPrivateKey *srpPrv; |
| 10356 + SRPKeyPairParams keyPairParams; |
| 10357 + |
| 10358 + PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 10359 + if (!arena) goto no_memory; |
| 10360 + |
| 10361 + keyPairParams.N.data = srpParams->N.data; |
| 10362 + keyPairParams.N.len = srpParams->N.len; |
| 10363 + keyPairParams.g.data = srpParams->g.data; |
| 10364 + keyPairParams.g.len = srpParams->g.len; |
| 10365 + keyPairParams.secret.data = srpParams->secret.data; |
| 10366 + keyPairParams.secret.len = srpParams->secret.len; |
| 10367 + |
| 10368 + rv = SRP_NewServerKeyPair(&srpPrv, &keyPairParams); |
| 10369 + if (rv != SECSuccess) { |
| 10370 + ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); |
| 10371 + return rv; |
| 10372 + } |
| 10373 + prvKey = (SECKEYPrivateKey *)srpPrv; |
| 10374 + |
| 10375 + /* create pubKey from temporary stuff */ |
| 10376 + pubKey = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); |
| 10377 + if (!pubKey) goto no_memory; |
| 10378 + pubKey->arena = arena; |
| 10379 + srp = &pubKey->u.srp; |
| 10380 + |
| 10381 + SECITEM_CopyItem(arena, &srp->N, &srpParams->N); |
| 10382 + SECITEM_CopyItem(arena, &srp->g, &srpParams->g); |
| 10383 + SECITEM_CopyItem(arena, &srp->s, &srpParams->s); |
| 10384 + SECITEM_CopyItem(arena, &srp->u, &srpParams->u); |
| 10385 + SECITEM_CopyItem(arena, &srp->pub, &srpPrv->pubKey); |
| 10386 + |
| 10387 + } else { |
| 10388 + |
| 10389 + /* input: srpParams, output: prvKey = b,B,v, pubKey = N,g,s,u,B */ |
| 10390 + prvKey = SECKEY_CreateSRPPrivateKey(srpParams, &pubKey, PR_TRUE, NULL); |
| 10391 + if (!prvKey) { |
| 10392 + ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); |
| 10393 + rv = SECFailure; |
| 10394 + goto cleanup; |
| 10395 + } |
| 10396 + srp = &pubKey->u.srp; |
| 10397 + } |
| 10398 + |
| 10399 + /* send N,g,s,B as ServerKeyExchange to Client */ |
| 10400 + /* optionally include signature for additional DSS/RSA auth */ |
| 10401 + |
| 10402 + if (kea_def->kea != kea_srp) { /* we need a RSA/DSA signature */ |
| 10403 + rv = ssl3_ComputeSRPKeyHash(&srp->N, &srp->g, &srp->s, &srp->pub, |
| 10404 + &ss->ssl3.hs.client
_random, |
| 10405 + &ss->ssl3.hs.server
_random, |
| 10406 + &hashes, ss->opt.by
passPKCS11); |
| 10407 + if (rv != SECSuccess) { |
| 10408 + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
| 10409 + goto loser; |
| 10410 + } |
| 10411 + /* look if we have a certificate for selected algo */ |
| 10412 + if (kea_def->kea == kea_srp_rsa) |
| 10413 + bytes = kt_rsa; |
| 10414 + else |
| 10415 + bytes = kt_null; |
| 10416 + |
| 10417 + if (!(&ss->serverCerts[bytes])) { |
| 10418 + /* ciphersuite signing algo does not match supplied certificate */ |
| 10419 + PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); |
| 10420 + return SECFailure; |
| 10421 + } |
| 10422 + rv = ssl3_SignHashes(&hashes, ss->serverCerts[bytes].SERVERKEY, |
| 10423 + &signed_hash, PR_TRUE); |
| 10424 + bytes = 2 + signed_hash.len; |
| 10425 + } |
| 10426 + |
| 10427 + bytes += srp->N.len + srp->g.len + srp->s.len + srp->pub.len + 7; |
| 10428 + |
| 10429 + rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, bytes); |
| 10430 + if (rv != SECSuccess) |
| 10431 + return rv; /* err set by AppendHandshake. */ |
| 10432 + |
| 10433 + rv = ssl3_AppendHandshakeVariable(ss, srp->N.data, srp->N.len, 2); |
| 10434 + if (rv != SECSuccess) |
| 10435 + return rv; /* err set by AppendHandshake. */ |
| 10436 + |
| 10437 + rv = ssl3_AppendHandshakeVariable(ss, srp->g.data, srp->g.len, 2); |
| 10438 + if (rv != SECSuccess) |
| 10439 + return rv; /* err set by AppendHandshake. */ |
| 10440 + |
| 10441 + rv = ssl3_AppendHandshakeVariable(ss, srp->s.data, srp->s.len, 1); |
| 10442 + if (rv != SECSuccess) |
| 10443 + return rv; /* err set by AppendHandshake. */ |
| 10444 + |
| 10445 + rv = ssl3_AppendHandshakeVariable(ss, srp->pub.data, srp->pub.len, 2); |
| 10446 + if (rv != SECSuccess) |
| 10447 + return rv; /* err set by AppendHandshake. */ |
| 10448 + |
| 10449 + if (kea_def->kea != kea_srp) { |
| 10450 + rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data, |
| 10451 + signed_hash.len, 2); |
| 10452 + if (rv != SECSuccess) { |
| 10453 + return rv; /* err set by AppendHandshake. */ |
| 10454 + } |
| 10455 + SECITEM_FreeItem(&signed_hash, PR_FALSE); |
| 10456 + } |
| 10457 + |
| 10458 + /* save prvKey / pubKey for use in HandleSRPClientExchange |
| 10459 + * XXX in bypassPK11, prvKey is no PK11 object and must be casted */ |
| 10460 + ssl3KeyPair *srpPair = ssl3_NewKeyPair(prvKey, pubKey); |
| 10461 + ss->serverCerts[kt_srp].serverKeyPair = srpPair; |
| 10462 + |
| 10463 +cleanup: |
| 10464 + SECITEM_FreeItem(&srpParams->N, PR_FALSE); |
| 10465 + SECITEM_FreeItem(&srpParams->g, PR_FALSE); |
| 10466 + SECITEM_FreeItem(&srpParams->s, PR_FALSE); |
| 10467 + SECITEM_ZfreeItem(&srpParams->secret, PR_FALSE); |
| 10468 + SECITEM_FreeItem(ss->sec.userName, PR_TRUE); |
| 10469 + if (srpParams) PORT_Free(srpParams); |
| 10470 + return rv; |
| 10471 +loser: |
| 10472 + PORT_SetError(SSL_ERROR_INTERNAL_ERROR_ALERT); |
| 10473 + (void)SSL3_SendAlert(ss, alert_fatal, internal_error); |
| 10474 + return SECFailure; |
| 10475 +unknown_id: |
| 10476 + PORT_SetError(SSL_ERROR_UNKNOWN_PSK_IDENTITY_ALERT); |
| 10477 + (void)SSL3_SendAlert(ss, alert_fatal, unknown_psk_identity); |
| 10478 + return SECFailure; |
| 10479 +no_memory: |
| 10480 + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
| 10481 + return SECFailure; |
| 10482 +} |
| 10483 |
| 10484 static SECStatus |
| 10485 ssl3_SendServerKeyExchange(sslSocket *ss) |
| 10486 @@ -7183,7 +7723,9 @@ const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; |
| 10487 return rv; |
| 10488 } |
| 10489 #endif /* NSS_ENABLE_ECC */ |
| 10490 - |
| 10491 + case kt_srp: |
| 10492 + rv = ssl3_SendSRPServerKeyExchange(ss); |
| 10493 + return rv; |
| 10494 case kt_dh: |
| 10495 case kt_null: |
| 10496 default: |
| 10497 @@ -7536,6 +8078,101 @@ double_bypass: |
| 10498 return SECSuccess; |
| 10499 } |
| 10500 |
| 10501 +/* |
| 10502 + * extract SRP value A from ClientKeyExchange |
| 10503 + * calculate pre-master-secret and init cipher specs |
| 10504 + * |
| 10505 + * called by ssl3_HandleClientKeyExchange |
| 10506 + */ |
| 10507 +SECStatus |
| 10508 +ssl3_HandleSRPClientKeyExchange(sslSocket *ss, SSL3Opaque *b, |
| 10509 + PRUint32 length) { |
| 10510 + |
| 10511 + SECItem ppub; /* peers public key ('A') */ |
| 10512 + sslServerCerts sc; |
| 10513 + SECStatus rv = SECFailure; |
| 10514 + SECKEYPublicKey *pubKey = NULL; |
| 10515 + |
| 10516 + |
| 10517 + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
| 10518 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
| 10519 + |
| 10520 + rv = ssl3_ConsumeHandshakeVariable(ss, &ppub, 2, &b, &length); |
| 10521 + if (rv != SECSuccess) { |
| 10522 + PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); |
| 10523 + return SECFailure; |
| 10524 + } |
| 10525 + |
| 10526 + sc = ss->serverCerts[kt_srp]; |
| 10527 + pubKey = sc.serverKeyPair->pubKey; |
| 10528 + |
| 10529 + SECITEM_CopyItem(pubKey->arena, &pubKey->u.srp.ppub, &ppub); |
| 10530 + |
| 10531 + if (ss->opt.bypassPKCS11) { |
| 10532 + SRPPrivateKey *prvKey = NULL; |
| 10533 + SECItem pms = { 0, NULL, 0 }; |
| 10534 + SRPDeriveParams param; |
| 10535 + |
| 10536 + prvKey = (SRPPrivateKey *)sc.serverKeyPair->privKey; |
| 10537 + |
| 10538 + param.N.data = pubKey->u.srp.N.data; |
| 10539 + param.N.len = pubKey->u.srp.N.len; |
| 10540 + param.g.data = pubKey->u.srp.g.data; |
| 10541 + param.g.len = pubKey->u.srp.g.len; |
| 10542 + param.ppub.data = pubKey->u.srp.ppub.data; |
| 10543 + param.ppub.len = pubKey->u.srp.ppub.len; |
| 10544 + |
| 10545 + if (SECSuccess != SRP_ServerDerive(prvKey, ¶m, &pms)) |
| 10546 + goto derive_fail; |
| 10547 + |
| 10548 + ssl_GetSpecWriteLock(ss); |
| 10549 + /* create MS out of MS, bypassing PKCS11 */ |
| 10550 + rv = ssl3_MasterKeyDeriveBypass(ss->ssl3.pwSpec, |
| 10551 + (unsigned char *)&ss->ssl3.hs.client_random, |
| 10552 + (unsigned char *)&ss->ssl3.hs.server_random, |
| 10553 + &pms, PR_TRUE, PR_FALSE); |
| 10554 + if (rv != SECSuccess) { |
| 10555 + ss->ssl3.pwSpec->msItem.data = ss->ssl3.pwSpec->raw_master_secret; |
| 10556 + ss->ssl3.pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; |
| 10557 + PK11_GenerateRandom(ss->ssl3.pwSpec->msItem.data, ss->ssl3.pwSpec->
msItem.len); |
| 10558 + } |
| 10559 + |
| 10560 + rv = ssl3_InitPendingCipherSpec(ss, NULL); |
| 10561 + |
| 10562 + SECITEM_ZfreeItem(&pms, PR_FALSE); |
| 10563 + PORT_FreeArena(prvKey->arena, PR_TRUE); /* XXX FreeArena does not zeroi
ze! */ |
| 10564 + sc.serverKeyPair->privKey = NULL; |
| 10565 + |
| 10566 + } else { |
| 10567 + SECKEYPrivateKey *prvKey = NULL; |
| 10568 + PK11SymKey *pms = NULL; /* pre-master secret */ |
| 10569 + |
| 10570 + prvKey = sc.serverKeyPair->privKey; |
| 10571 + |
| 10572 + /* Calculate PMS based on clntKey and public params */ |
| 10573 + pms = PK11_PubDerive(prvKey, pubKey, PR_TRUE, NULL, NULL, |
| 10574 + CKM_NSS_SRP_DERIVE, CKM_TLS_MASTER_KEY_DERIVE, CKF_D
ERIVE, 0, NULL); |
| 10575 + |
| 10576 + if (!pms) { |
| 10577 + goto derive_fail; |
| 10578 + } |
| 10579 + |
| 10580 + ssl_GetSpecWriteLock(ss); |
| 10581 + /* derive master secret from pms */ |
| 10582 + rv = ssl3_InitPendingCipherSpec(ss, pms); |
| 10583 + ssl_ReleaseSpecWriteLock(ss); |
| 10584 + |
| 10585 + PK11_FreeSymKey(pms); |
| 10586 + /*SECKEY_DestroyPrivateKey(prvKey);*/ |
| 10587 + } |
| 10588 + |
| 10589 + return rv; |
| 10590 +derive_fail: |
| 10591 + if (PORT_GetError() == SEC_ERROR_SRP_ILLEGAL_PARAMETER) |
| 10592 + SSL3_SendAlert(ss, alert_fatal, illegal_parameter); |
| 10593 + return rv; |
| 10594 +} |
| 10595 + |
| 10596 |
| 10597 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete |
| 10598 * ssl3 ClientKeyExchange message from the remote client |
| 10599 @@ -7608,7 +8245,8 @@ skip: |
| 10600 serverKey = serverKeyPair->privKey; |
| 10601 } |
| 10602 |
| 10603 - if (serverKey == NULL) { |
| 10604 + /* XXX hack, figure out this serverKey thing..*/ |
| 10605 + if (serverKey == NULL && kea_def->exchKeyType != kt_srp) { |
| 10606 SEND_ALERT |
| 10607 PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG); |
| 10608 return SECFailure; |
| 10609 @@ -7649,7 +8287,12 @@ skip: |
| 10610 } |
| 10611 break; |
| 10612 #endif /* NSS_ENABLE_ECC */ |
| 10613 - |
| 10614 + case kt_srp: |
| 10615 + rv = ssl3_HandleSRPClientKeyExchange(ss, b, length); |
| 10616 + if (rv != SECSuccess) { |
| 10617 + return SECFailure; /* error code set */ |
| 10618 + } |
| 10619 + break; |
| 10620 default: |
| 10621 (void) ssl3_HandshakeFailure(ss); |
| 10622 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); |
| 10623 @@ -7823,8 +8466,12 @@ ssl3_SendCertificate(sslSocket *ss) |
| 10624 * using EC certificates. |
| 10625 */ |
| 10626 if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) || |
| 10627 - (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) { |
| 10628 + (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) || |
| 10629 + (ss->ssl3.hs.kea_def->kea == kea_srp_rsa)) { |
| 10630 certIndex = kt_rsa; |
| 10631 + } else if |
| 10632 + (ss->ssl3.hs.kea_def->kea == kea_srp_dss) { |
| 10633 + certIndex = kt_null; |
| 10634 } else { |
| 10635 certIndex = ss->ssl3.hs.kea_def->exchKeyType; |
| 10636 } |
| 10637 @@ -8244,7 +8891,9 @@ cert_block: |
| 10638 ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa || |
| 10639 ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || |
| 10640 #endif /* NSS_ENABLE_ECC */ |
| 10641 - ss->ssl3.hs.kea_def->exchKeyType == kt_dh) { |
| 10642 + ss->ssl3.hs.kea_def->exchKeyType == kt_dh || |
| 10643 + ss->ssl3.hs.kea_def->kea == kea_srp_dss || |
| 10644 + ss->ssl3.hs.kea_def->kea == kea_srp_rsa) { |
| 10645 ss->ssl3.hs.ws = wait_server_key; /* allow server_key_exchange */ |
| 10646 } |
| 10647 } |
| 10648 diff --git a/net/third_party/nss/ssl/ssl3ecc.c b/net/third_party/nss/ssl/ssl3ecc
.c |
| 10649 index 778c7ab..b899038 100644 |
| 10650 --- a/net/third_party/nss/ssl/ssl3ecc.c |
| 10651 +++ b/net/third_party/nss/ssl/ssl3ecc.c |
| 10652 @@ -1191,3 +1191,60 @@ loser: |
| 10653 } |
| 10654 |
| 10655 #endif /* NSS_ENABLE_ECC */ |
| 10656 + |
| 10657 +/* send user mapping indication using info from ss->sec.userlogin |
| 10658 + * called from ssl3_CallHelloExtensionSenders */ |
| 10659 +PRInt32 |
| 10660 +ssl3_SendSRPHelloExtension(sslSocket * ss, PRBool append, |
| 10661 + PRUint32 maxBytes) |
| 10662 +{ |
| 10663 + SECItem * user = ss->sec.userName; |
| 10664 + |
| 10665 + if (user == NULL) |
| 10666 + return 0; /* no credentials, no extension */ |
| 10667 + |
| 10668 + if (append && maxBytes >= user->len + 5) { |
| 10669 + SECStatus rv; |
| 10670 + /* extension_type 6 */ |
| 10671 + rv = ssl3_AppendHandshakeNumber(ss, 12, 2); |
| 10672 + if (rv != SECSuccess) return 0; |
| 10673 + /* length of extension */ |
| 10674 + rv = ssl3_AppendHandshakeNumber(ss, user->len + 1, 2); |
| 10675 + if (rv != SECSuccess) return 0; |
| 10676 + /* length of data */ |
| 10677 + rv = ssl3_AppendHandshakeNumber(ss, user->len, 1); |
| 10678 + if (rv != SECSuccess) return 0; |
| 10679 + /* extension_data = srp user name */ |
| 10680 + rv = ssl3_AppendHandshake(ss, user->data, user->len); |
| 10681 + if (rv != SECSuccess) return 0; |
| 10682 + } |
| 10683 + return user->len+5; |
| 10684 +} |
| 10685 + |
| 10686 +SECStatus |
| 10687 +ssl3_HandleSRPHelloExtension(sslSocket *ss, PRUint16 ext, SECItem *data) |
| 10688 +{ |
| 10689 + SECStatus rv; |
| 10690 + SECItem username; |
| 10691 + |
| 10692 + rv = ssl3_ConsumeHandshakeVariable(ss, &username, 1, &data->data, &data-
>len); |
| 10693 + if (rv != SECSuccess) |
| 10694 + return rv; |
| 10695 + |
| 10696 + /* enforce SRP username length constrain */ |
| 10697 + if (data->len > MAX_SRP_USERNAME_LENGTH) |
| 10698 + data->len = MAX_SRP_USERNAME_LENGTH; |
| 10699 + |
| 10700 + ss->sec.userName = PORT_ZAlloc(sizeof(SECItem)); |
| 10701 + if (!ss->sec.userName) |
| 10702 + goto no_memory; |
| 10703 + |
| 10704 + rv = SECITEM_CopyItem(NULL, ss->sec.userName, &username); |
| 10705 + if (rv != SECSuccess) |
| 10706 + goto no_memory; |
| 10707 + |
| 10708 + return rv; |
| 10709 +no_memory: |
| 10710 + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
| 10711 + return SECFailure; |
| 10712 +} |
| 10713 diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext
.c |
| 10714 index b93671e..c2a27b4 100644 |
| 10715 --- a/net/third_party/nss/ssl/ssl3ext.c |
| 10716 +++ b/net/third_party/nss/ssl/ssl3ext.c |
| 10717 @@ -78,6 +78,11 @@ static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket * ss, |
| 10718 PRBool append, PRUint32 maxBytes); |
| 10719 static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, |
| 10720 PRUint16 ex_type, SECItem *data); |
| 10721 +static SECStatus ssl3_HandleSRPHelloXtn(sslSocket *ss, PRUint16 ext, |
| 10722 + SECItem *data); |
| 10723 +PRInt32 ssl3_SendSRPHelloXtn(sslSocket * ss, PRBool append, |
| 10724 + PRUint32 maxBytes); |
| 10725 + |
| 10726 |
| 10727 /* |
| 10728 * Write bytes. Using this function means the SECItem structure |
| 10729 @@ -254,6 +259,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTL
S[] = { |
| 10730 |
| 10731 static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = { |
| 10732 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
| 10733 + { ssl_srp_hello_xtn, &ssl3_HandleSRPHelloXtn }, |
| 10734 { -1, NULL } |
| 10735 }; |
| 10736 |
| 10737 @@ -272,6 +278,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTEN
SIONS] = { |
| 10738 { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
| 10739 #endif |
| 10740 { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
| 10741 + { ssl_srp_hello_xtn, &ssl3_SendSRPHelloXtn }, |
| 10742 { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
| 10743 { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
| 10744 { ssl_snap_start_xtn, &ssl3_SendSnapStartXtn } |
| 10745 @@ -1720,3 +1727,59 @@ ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 e
x_type, SECItem *data) |
| 10746 return rv; |
| 10747 } |
| 10748 |
| 10749 +/* send user mapping indication using info from ss->sec.userlogin |
| 10750 + * called from ssl3_CallHelloExtensionSenders */ |
| 10751 +PRInt32 |
| 10752 +ssl3_SendSRPHelloXtn(sslSocket * ss, PRBool append, |
| 10753 + PRUint32 maxBytes) |
| 10754 +{ |
| 10755 + SECItem * user = ss->sec.userName; |
| 10756 + |
| 10757 + if (user == NULL) |
| 10758 + return 0; /* no credentials, no extension */ |
| 10759 + |
| 10760 + if (append && maxBytes >= user->len + 5) { |
| 10761 + SECStatus rv; |
| 10762 + /* extension_type 6 */ |
| 10763 + rv = ssl3_AppendHandshakeNumber(ss, 12, 2); |
| 10764 + if (rv != SECSuccess) return 0; |
| 10765 + /* length of extension */ |
| 10766 + rv = ssl3_AppendHandshakeNumber(ss, user->len + 1, 2); |
| 10767 + if (rv != SECSuccess) return 0; |
| 10768 + /* length of data */ |
| 10769 + rv = ssl3_AppendHandshakeNumber(ss, user->len, 1); |
| 10770 + if (rv != SECSuccess) return 0; |
| 10771 + /* extension_data = srp user name */ |
| 10772 + rv = ssl3_AppendHandshake(ss, user->data, user->len); |
| 10773 + if (rv != SECSuccess) return 0; |
| 10774 + } |
| 10775 + return user->len+5; |
| 10776 +} |
| 10777 + |
| 10778 +SECStatus |
| 10779 +ssl3_HandleSRPHelloXtn(sslSocket *ss, PRUint16 ext, SECItem *data) |
| 10780 +{ |
| 10781 + SECStatus rv; |
| 10782 + SECItem username; |
| 10783 + |
| 10784 + rv = ssl3_ConsumeHandshakeVariable(ss, &username, 1, &data->data, &data-
>len); |
| 10785 + if (rv != SECSuccess) |
| 10786 + return rv; |
| 10787 + |
| 10788 + /* enforce SRP username length constrain */ |
| 10789 + if (data->len > MAX_SRP_USERNAME_LENGTH) |
| 10790 + data->len = MAX_SRP_USERNAME_LENGTH; |
| 10791 + |
| 10792 + ss->sec.userName = PORT_ZAlloc(sizeof(SECItem)); |
| 10793 + if (!ss->sec.userName) |
| 10794 + goto no_memory; |
| 10795 + |
| 10796 + rv = SECITEM_CopyItem(NULL, ss->sec.userName, &username); |
| 10797 + if (rv != SECSuccess) |
| 10798 + goto no_memory; |
| 10799 + |
| 10800 + return rv; |
| 10801 +no_memory: |
| 10802 + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); |
| 10803 + return SECFailure; |
| 10804 +} |
| 10805 diff --git a/net/third_party/nss/ssl/ssl3prot.h b/net/third_party/nss/ssl/ssl3pr
ot.h |
| 10806 index aeaacdd..a043577 100644 |
| 10807 --- a/net/third_party/nss/ssl/ssl3prot.h |
| 10808 +++ b/net/third_party/nss/ssl/ssl3prot.h |
| 10809 @@ -63,6 +63,8 @@ typedef uint16 ssl3CipherSuite; |
| 10810 |
| 10811 #define MAX_FRAGMENT_LENGTH 16384 |
| 10812 |
| 10813 +#define MAX_SRP_USERNAME_LENGTH 255 |
| 10814 + |
| 10815 typedef enum { |
| 10816 content_change_cipher_spec = 20, |
| 10817 content_alert = 21, |
| 10818 @@ -137,7 +139,9 @@ typedef enum { |
| 10819 certificate_unobtainable = 111, |
| 10820 unrecognized_name = 112, |
| 10821 bad_certificate_status_response = 113, |
| 10822 - bad_certificate_hash_value = 114 |
| 10823 + bad_certificate_hash_value = 114, |
| 10824 + |
| 10825 + unknown_psk_identity = 115 |
| 10826 |
| 10827 } SSL3AlertDescription; |
| 10828 |
| 10829 @@ -215,6 +219,9 @@ typedef enum { |
| 10830 kea_dh_anon, |
| 10831 kea_dh_anon_export, |
| 10832 kea_rsa_fips, |
| 10833 + kea_srp, |
| 10834 + kea_srp_rsa, |
| 10835 + kea_srp_dss, |
| 10836 kea_ecdh_ecdsa, |
| 10837 kea_ecdhe_ecdsa, |
| 10838 kea_ecdh_rsa, |
| 10839 diff --git a/net/third_party/nss/ssl/sslauth.c b/net/third_party/nss/ssl/sslauth
.c |
| 10840 index 3f4924d..12c9a12 100644 |
| 10841 --- a/net/third_party/nss/ssl/sslauth.c |
| 10842 +++ b/net/third_party/nss/ssl/sslauth.c |
| 10843 @@ -291,6 +291,80 @@ SSL_SetPKCS11PinArg(PRFileDesc *s, void *arg) |
| 10844 return SECSuccess; |
| 10845 } |
| 10846 |
| 10847 +/* register callback function to provide the user password */ |
| 10848 +SECStatus |
| 10849 +SSL_UserPasswdHook(PRFileDesc *s, SSLUserPasswdCB func, void *arg) |
| 10850 +{ |
| 10851 + sslSocket *ss; |
| 10852 + |
| 10853 + ss = ssl_FindSocket(s); |
| 10854 + if (!ss) { |
| 10855 + SSL_DBG(("%d: SSL[%d]: bad socket in UserPasswdHook", |
| 10856 + SSL_GETPID(), s)); |
| 10857 + return SECFailure; |
| 10858 + } |
| 10859 + |
| 10860 + ss->getUserPasswd = func; |
| 10861 + ss->getUserPasswdArg = arg; |
| 10862 + return SECSuccess; |
| 10863 +} |
| 10864 + |
| 10865 +/* used by client to provide user credentials non-interactively */ |
| 10866 +SECStatus |
| 10867 +SSL_SetUserLogin(PRFileDesc *s, char *user, char *passwd) |
| 10868 +{ |
| 10869 + sslSocket *ss = NULL; |
| 10870 + int len; |
| 10871 + |
| 10872 + ss = ssl_FindSocket(s); |
| 10873 + if (!ss) { |
| 10874 + SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", |
| 10875 + SSL_GETPID(), s)); |
| 10876 + return SECFailure; |
| 10877 + } |
| 10878 + |
| 10879 + if (user) { |
| 10880 + len = PORT_Strlen(user); |
| 10881 + if (len > MAX_SRP_USERNAME_LENGTH) |
| 10882 + len = MAX_SRP_USERNAME_LENGTH; |
| 10883 + ss->sec.userName = SECITEM_AllocItem(NULL, NULL, len); |
| 10884 + if (!ss->sec.userName) { |
| 10885 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 10886 + return SECFailure; |
| 10887 + } |
| 10888 + PORT_Memcpy(ss->sec.userName->data, user, ss->sec.userName->len); |
| 10889 + } |
| 10890 + |
| 10891 + if (passwd) { |
| 10892 + len = PORT_Strlen(passwd); |
| 10893 + ss->sec.userPasswd = SECITEM_AllocItem(NULL, NULL, len); |
| 10894 + if (!ss->sec.userPasswd) { |
| 10895 + PORT_SetError(SEC_ERROR_NO_MEMORY); |
| 10896 + return SECFailure; |
| 10897 + } |
| 10898 + PORT_Memcpy(ss->sec.userPasswd->data, passwd, ss->sec.userPasswd->len); |
| 10899 + } |
| 10900 + |
| 10901 + return SECSuccess; |
| 10902 +} |
| 10903 + |
| 10904 +/* register callback function to provide SRP user authentication params */ |
| 10905 +SECStatus |
| 10906 +SSL_GetSRPParamsHook(PRFileDesc *s, SSLGetSRPParamsCB func, void *arg) |
| 10907 +{ |
| 10908 + sslSocket *ss; |
| 10909 + |
| 10910 + ss = ssl_FindSocket(s); |
| 10911 + if (!ss) { |
| 10912 + SSL_DBG(("%d: SSL[%d]: bad socket in GetClientAuthDataHook", |
| 10913 + SSL_GETPID(), s)); |
| 10914 + return SECFailure; |
| 10915 + } |
| 10916 + |
| 10917 + ss->getSRPParams = func; |
| 10918 + ss->getSRPParamsArg = arg; |
| 10919 + return SECSuccess; |
| 10920 +} |
| 10921 |
| 10922 /* This is the "default" authCert callback function. It is called when a |
| 10923 * certificate message is received from the peer and the local application |
| 10924 diff --git a/net/third_party/nss/ssl/sslenum.c b/net/third_party/nss/ssl/sslenum
.c |
| 10925 index b8aa8cc..196ed30 100644 |
| 10926 --- a/net/third_party/nss/ssl/sslenum.c |
| 10927 +++ b/net/third_party/nss/ssl/sslenum.c |
| 10928 @@ -74,6 +74,9 @@ const PRUint16 SSL_ImplementedCiphers[] = { |
| 10929 #endif /* NSS_ENABLE_ECC */ |
| 10930 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, |
| 10931 TLS_RSA_WITH_AES_256_CBC_SHA, |
| 10932 + TLS_SRP_SHA_WITH_AES_256_CBC_SHA, |
| 10933 + TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, |
| 10934 + TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, |
| 10935 |
| 10936 /* 128-bit */ |
| 10937 #ifdef NSS_ENABLE_ECC |
| 10938 @@ -98,12 +101,16 @@ const PRUint16 SSL_ImplementedCiphers[] = { |
| 10939 SSL_RSA_WITH_RC4_128_MD5, |
| 10940 SSL_RSA_WITH_RC4_128_SHA, |
| 10941 TLS_RSA_WITH_AES_128_CBC_SHA, |
| 10942 + TLS_SRP_SHA_WITH_AES_128_CBC_SHA, |
| 10943 + TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, |
| 10944 + TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, |
| 10945 |
| 10946 /* 112-bit 3DES */ |
| 10947 #ifdef NSS_ENABLE_ECC |
| 10948 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, |
| 10949 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, |
| 10950 #endif /* NSS_ENABLE_ECC */ |
| 10951 + TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, |
| 10952 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, |
| 10953 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, |
| 10954 #ifdef NSS_ENABLE_ECC |
| 10955 @@ -112,6 +119,8 @@ const PRUint16 SSL_ImplementedCiphers[] = { |
| 10956 #endif /* NSS_ENABLE_ECC */ |
| 10957 SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, |
| 10958 SSL_RSA_WITH_3DES_EDE_CBC_SHA, |
| 10959 + TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, |
| 10960 + TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, |
| 10961 |
| 10962 /* 56-bit DES "domestic" cipher suites */ |
| 10963 SSL_DHE_RSA_WITH_DES_CBC_SHA, |
| 10964 diff --git a/net/third_party/nss/ssl/sslerr.h b/net/third_party/nss/ssl/sslerr.h |
| 10965 index eb56ea9..a0c4b9d 100644 |
| 10966 --- a/net/third_party/nss/ssl/sslerr.h |
| 10967 +++ b/net/third_party/nss/ssl/sslerr.h |
| 10968 @@ -205,6 +205,8 @@ SSL_ERROR_WEAK_SERVER_KEY = (SSL_ERROR_BASE +
115), |
| 10969 |
| 10970 SSL_ERROR_RX_UNEXPECTED_CERT_STATUS = (SSL_ERROR_BASE + 116), |
| 10971 |
| 10972 +SSL_ERROR_UNKNOWN_PSK_IDENTITY_ALERT = (SSL_ERROR_BASE + 116), |
| 10973 + |
| 10974 SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ |
| 10975 } SSLErrorCodes; |
| 10976 #endif /* NO_SECURITY_ERROR_ENUM */ |
| 10977 diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl
.h |
| 10978 index 1ea82da..9eed38b 100644 |
| 10979 --- a/net/third_party/nss/ssl/sslimpl.h |
| 10980 +++ b/net/third_party/nss/ssl/sslimpl.h |
| 10981 @@ -317,9 +317,10 @@ typedef struct { |
| 10982 } ssl3CipherSuiteCfg; |
| 10983 |
| 10984 #ifdef NSS_ENABLE_ECC |
| 10985 -#define ssl_V3_SUITES_IMPLEMENTED 50 |
| 10986 +#define ssl_V3_SUITES_IMPLEMENTED 60 |
| 10987 #else |
| 10988 -#define ssl_V3_SUITES_IMPLEMENTED 30 |
| 10989 +#define ssl_V3_SUITES_IMPLEMENTED 60 |
| 10990 +/* TODO(sqs): where do these #s come from? I think sslsock.c, where we added 9
more SRP suites. before tls-srp patch, these were 59 and 39. */ |
| 10991 #endif /* NSS_ENABLE_ECC */ |
| 10992 |
| 10993 typedef struct sslOptionsStr { |
| 10994 @@ -1050,6 +1051,8 @@ struct sslSecurityInfoStr { |
| 10995 CERTCertificate *localCert; /* ssl 2
& 3 */ |
| 10996 CERTCertificate *peerCert; /* ssl 2 & 3 */ |
| 10997 SECKEYPublicKey *peerKey; /* ssl3 only */ |
| 10998 + SECItem *userName; /* SSL username credential */ |
| 10999 + SECItem *userPasswd; /* SSL userpasswd credential */ |
| 11000 |
| 11001 SSLSignType authAlgorithm; |
| 11002 PRUint32 authKeyBits; |
| 11003 @@ -1159,6 +1162,10 @@ const unsigned char * preferredCipher; |
| 11004 SSLHandshakeCallback handshakeCallback; |
| 11005 void *handshakeCallbackData; |
| 11006 void *pkcs11PinArg; |
| 11007 + SSLUserPasswdCB getUserPasswd; |
| 11008 + void *getUserPasswdArg; |
| 11009 + SSLGetSRPParamsCB getSRPParams; |
| 11010 + void *getSRPParamsArg; |
| 11011 |
| 11012 PRIntervalTime rTimeout; /* timeout for NSPR I/O */ |
| 11013 PRIntervalTime wTimeout; /* timeout for NSPR I/O */ |
| 11014 diff --git a/net/third_party/nss/ssl/sslproto.h b/net/third_party/nss/ssl/sslpro
to.h |
| 11015 index b534d0b..cbf6250 100644 |
| 11016 --- a/net/third_party/nss/ssl/sslproto.h |
| 11017 +++ b/net/third_party/nss/ssl/sslproto.h |
| 11018 @@ -220,6 +220,16 @@ |
| 11019 #define TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018 |
| 11020 #define TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019 |
| 11021 |
| 11022 +#define TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA 0xC01A |
| 11023 +#define TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0xC01B |
| 11024 +#define TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0xC01C |
| 11025 +#define TLS_SRP_SHA_WITH_AES_128_CBC_SHA 0xC01D |
| 11026 +#define TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0xC01E |
| 11027 +#define TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0xC01F |
| 11028 +#define TLS_SRP_SHA_WITH_AES_256_CBC_SHA 0xC020 |
| 11029 +#define TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0xC021 |
| 11030 +#define TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0xC022 |
| 11031 + |
| 11032 /* Netscape "experimental" cipher suites. */ |
| 11033 #define SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA 0xffe0 |
| 11034 #define SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA 0xffe1 |
| 11035 diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock
.c |
| 11036 index b14a935..18ee612 100644 |
| 11037 --- a/net/third_party/nss/ssl/sslsock.c |
| 11038 +++ b/net/third_party/nss/ssl/sslsock.c |
| 11039 @@ -102,6 +102,15 @@ static cipherPolicy ssl_ciphers[] = { /* Export
France */ |
| 11040 { TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11041 { TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALL
OWED }, |
| 11042 { TLS_RSA_WITH_SEED_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11043 + { TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11044 + { TLS_SRP_SHA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11045 + { TLS_SRP_SHA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11046 + { TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11047 + { TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11048 + { TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11049 + { TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11050 + { TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11051 + { TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, |
| 11052 { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_ALLOWED, SSL_NOT_ALLOWED }, |
| 11053 { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_ALLOWED, SSL_NOT_ALLOWED }, |
| 11054 #ifdef NSS_ENABLE_ECC |
| 11055 diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h |
| 11056 index 3fa3f9b..172364c 100644 |
| 11057 --- a/net/third_party/nss/ssl/sslt.h |
| 11058 +++ b/net/third_party/nss/ssl/sslt.h |
| 11059 @@ -74,6 +74,7 @@ typedef enum { |
| 11060 ssl_kea_dh = 2, |
| 11061 ssl_kea_fortezza = 3, /* deprecated, now unused */ |
| 11062 ssl_kea_ecdh = 4, |
| 11063 + ssl_kea_srp = 5, |
| 11064 ssl_kea_size /* number of ssl_kea_ algorithms */ |
| 11065 } SSLKEAType; |
| 11066 |
| 11067 @@ -88,6 +89,7 @@ typedef enum { |
| 11068 #define kt_fortezza ssl_kea_fortezza /* deprecated, now unused */ |
| 11069 #define kt_ecdh ssl_kea_ecdh |
| 11070 #define kt_kea_size ssl_kea_size |
| 11071 +#define kt_srp ssl_kea_srp |
| 11072 |
| 11073 typedef enum { |
| 11074 ssl_sign_null = 0, |
| 11075 @@ -203,13 +205,14 @@ typedef enum { |
| 11076 ssl_elliptic_curves_xtn = 10, |
| 11077 ssl_ec_point_formats_xtn = 11, |
| 11078 #endif |
| 11079 + ssl_srp_hello_xtn = 12, |
| 11080 ssl_session_ticket_xtn = 35, |
| 11081 ssl_next_proto_neg_xtn = 13172, |
| 11082 ssl_snap_start_xtn = 13174, |
| 11083 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ |
| 11084 } SSLExtensionType; |
| 11085 |
| 11086 -#define SSL_MAX_EXTENSIONS 8 |
| 11087 +#define SSL_MAX_EXTENSIONS 9 |
| 11088 |
| 11089 typedef enum { |
| 11090 /* No Snap Start handshake was attempted. */ |
OLD | NEW |