root/source4/heimdal/lib/hcrypto/bn.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. BN_new
  2. BN_free
  3. BN_clear
  4. BN_clear_free
  5. BN_dup
  6. BN_num_bits
  7. BN_num_bytes
  8. BN_bin2bn
  9. BN_bn2bin
  10. BN_hex2bn
  11. BN_bn2hex
  12. BN_cmp
  13. BN_set_negative
  14. BN_is_negative
  15. BN_is_bit_set
  16. BN_set_bit
  17. BN_clear_bit
  18. BN_set_word
  19. BN_get_word
  20. BN_rand
  21. BN_uadd
  22. BN_GENCB_set
  23. BN_GENCB_call

   1 /*
   2  * Copyright (c) 2006 Kungliga Tekniska Högskolan
   3  * (Royal Institute of Technology, Stockholm, Sweden).
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the Institute nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #ifdef HAVE_CONFIG_H
  35 #include <config.h>
  36 #endif
  37 
  38 RCSID("$Id$");
  39 
  40 #include <stdio.h>
  41 #include <stdlib.h>
  42 #include <string.h>
  43 #include <limits.h>
  44 
  45 #include <krb5-types.h>
  46 #include <rfc2459_asn1.h> /* XXX */
  47 #include <der.h>
  48 
  49 #include <bn.h>
  50 #include <rand.h>
  51 #include <hex.h>
  52 
  53 BIGNUM *
  54 BN_new(void)
     /* [<][>][^][v][top][bottom][index][help] */
  55 {
  56     heim_integer *hi;
  57     hi = calloc(1, sizeof(*hi));
  58     return (BIGNUM *)hi;
  59 }
  60 
  61 void
  62 BN_free(BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
  63 {
  64     BN_clear(bn);
  65     free(bn);
  66 }
  67 
  68 void
  69 BN_clear(BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
  70 {
  71     heim_integer *hi = (heim_integer *)bn;
  72     if (hi->data) {
  73         memset(hi->data, 0, hi->length);
  74         free(hi->data);
  75     }
  76     memset(hi, 0, sizeof(*hi));
  77 }
  78 
  79 void
  80 BN_clear_free(BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
  81 {
  82     BN_free(bn);
  83 }
  84 
  85 BIGNUM *
  86 BN_dup(const BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88     BIGNUM *b = BN_new();
  89     if (der_copy_heim_integer((const heim_integer *)bn, (heim_integer *)b)) {
  90         BN_free(b);
  91         return NULL;
  92     }
  93     return b;
  94 }
  95 
  96 /*
  97  * If the caller really want to know the number of bits used, subtract
  98  * one from the length, multiply by 8, and then lookup in the table
  99  * how many bits the hightest byte uses.
 100  */
 101 int
 102 BN_num_bits(const BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104     static unsigned char num2bits[256] = {
 105         0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,  5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
 106         6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
 107         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
 108         7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
 109         8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 110         8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 111         8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 112         8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 113     };
 114     const heim_integer *i = (const void *)bn;
 115     if (i->length == 0)
 116         return 0;
 117     return (i->length - 1) * 8 + num2bits[((unsigned char *)i->data)[0]];
 118 }
 119 
 120 int
 121 BN_num_bytes(const BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
 122 {
 123     return ((const heim_integer *)bn)->length;
 124 }
 125 
 126 /*
 127  * Ignore negative flag.
 128  */
 129 
 130 BIGNUM *
 131 BN_bin2bn(const void *s, int len, BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
 132 {
 133     heim_integer *hi = (void *)bn;
 134 
 135     if (len < 0)
 136         return NULL;
 137 
 138     if (hi == NULL) {
 139         hi = (heim_integer *)BN_new();
 140         if (hi == NULL)
 141             return NULL;
 142     }
 143     if (hi->data)
 144         BN_clear((BIGNUM *)hi);
 145     hi->negative = 0;
 146     hi->data = malloc(len);
 147     if (hi->data == NULL && len != 0) {
 148         if (bn == NULL)
 149             BN_free((BIGNUM *)hi);
 150         return NULL;
 151     }
 152     hi->length = len;
 153     memcpy(hi->data, s, len);
 154     return (BIGNUM *)hi;
 155 }
 156 
 157 int
 158 BN_bn2bin(const BIGNUM *bn, void *to)
     /* [<][>][^][v][top][bottom][index][help] */
 159 {
 160     const heim_integer *hi = (const void *)bn;
 161     memcpy(to, hi->data, hi->length);
 162     return hi->length;
 163 }
 164 
 165 int
 166 BN_hex2bn(BIGNUM **bnp, const char *in)
     /* [<][>][^][v][top][bottom][index][help] */
 167 {
 168     int negative;
 169     ssize_t ret;
 170     size_t len;
 171     void *data;
 172 
 173     len = strlen(in);
 174     data = malloc(len);
 175     if (data == NULL)
 176         return 0;
 177 
 178     if (*in == '-') {
 179         negative = 1;
 180         in++;
 181     } else
 182         negative = 0;
 183 
 184     ret = hex_decode(in, data, len);
 185     if (ret < 0) {
 186         free(data);
 187         return 0;
 188     }
 189 
 190     *bnp = BN_bin2bn(data, ret, NULL);
 191     free(data);
 192     if (*bnp == NULL)
 193         return 0;
 194     BN_set_negative(*bnp, negative);
 195     return 1;
 196 }
 197 
 198 char *
 199 BN_bn2hex(const BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
 200 {
 201     ssize_t ret;
 202     size_t len;
 203     void *data;
 204     char *str;
 205 
 206     len = BN_num_bytes(bn);
 207     data = malloc(len);
 208     if (data == NULL)
 209         return 0;
 210 
 211     len = BN_bn2bin(bn, data);
 212 
 213     ret = hex_encode(data, len, &str);
 214     free(data);
 215     if (ret < 0)
 216         return 0;
 217 
 218     return str;
 219 }
 220 
 221 int
 222 BN_cmp(const BIGNUM *bn1, const BIGNUM *bn2)
     /* [<][>][^][v][top][bottom][index][help] */
 223 {
 224     return der_heim_integer_cmp((const heim_integer *)bn1,
 225                                 (const heim_integer *)bn2);
 226 }
 227 
 228 void
 229 BN_set_negative(BIGNUM *bn, int flag)
     /* [<][>][^][v][top][bottom][index][help] */
 230 {
 231     ((heim_integer *)bn)->negative = (flag ? 1 : 0);
 232 }
 233 
 234 int
 235 BN_is_negative(const BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
 236 {
 237     return ((const heim_integer *)bn)->negative ? 1 : 0;
 238 }
 239 
 240 static const unsigned char is_set[8] = { 1, 2, 4, 8, 16, 32, 64, 128 };
 241 
 242 int
 243 BN_is_bit_set(const BIGNUM *bn, int bit)
     /* [<][>][^][v][top][bottom][index][help] */
 244 {
 245     heim_integer *hi = (heim_integer *)bn;
 246     unsigned char *p = hi->data;
 247 
 248     if ((bit / 8) > hi->length || hi->length == 0)
 249         return 0;
 250 
 251     return p[hi->length - 1 - (bit / 8)] & is_set[bit % 8];
 252 }
 253 
 254 int
 255 BN_set_bit(BIGNUM *bn, int bit)
     /* [<][>][^][v][top][bottom][index][help] */
 256 {
 257     heim_integer *hi = (heim_integer *)bn;
 258     unsigned char *p;
 259 
 260     if ((bit / 8) > hi->length || hi->length == 0) {
 261         size_t len = (bit + 7) / 8;
 262         void *d = realloc(hi->data, len);
 263         if (d == NULL)
 264             return 0;
 265         hi->data = d;
 266         p = hi->data;
 267         memset(&p[hi->length], 0, len);
 268         hi->length = len;
 269     } else
 270         p = hi->data;
 271 
 272     p[hi->length - 1 - (bit / 8)] |= is_set[bit % 8];
 273     return 1;
 274 }
 275 
 276 int
 277 BN_clear_bit(BIGNUM *bn, int bit)
     /* [<][>][^][v][top][bottom][index][help] */
 278 {
 279     heim_integer *hi = (heim_integer *)bn;
 280     unsigned char *p = hi->data;
 281 
 282     if ((bit / 8) > hi->length || hi->length == 0)
 283         return 0;
 284 
 285     p[hi->length - 1 - (bit / 8)] &= (unsigned char)(~(is_set[bit % 8]));
 286 
 287     return 1;
 288 }
 289 
 290 int
 291 BN_set_word(BIGNUM *bn, unsigned long num)
     /* [<][>][^][v][top][bottom][index][help] */
 292 {
 293     unsigned char p[sizeof(num)];
 294     unsigned long num2;
 295     int i, len;
 296 
 297     for (num2 = num, i = 0; num2 > 0; i++)
 298         num2 = num2 >> 8;
 299 
 300     len = i;
 301     for (; i > 0; i--) {
 302         p[i - 1] = (num & 0xff);
 303         num = num >> 8;
 304     }
 305 
 306     bn = BN_bin2bn(p, len, bn);
 307     return bn != NULL;
 308 }
 309 
 310 unsigned long
 311 BN_get_word(const BIGNUM *bn)
     /* [<][>][^][v][top][bottom][index][help] */
 312 {
 313     heim_integer *hi = (heim_integer *)bn;
 314     unsigned long num = 0;
 315     int i;
 316 
 317     if (hi->negative || hi->length > sizeof(num))
 318         return ULONG_MAX;
 319 
 320     for (i = 0; i < hi->length; i++)
 321         num = ((unsigned char *)hi->data)[i] | (num << 8);
 322     return num;
 323 }
 324 
 325 int
 326 BN_rand(BIGNUM *bn, int bits, int top, int bottom)
     /* [<][>][^][v][top][bottom][index][help] */
 327 {
 328     size_t len = (bits + 7) / 8;
 329     heim_integer *i = (heim_integer *)bn;
 330 
 331     BN_clear(bn);
 332 
 333     i->negative = 0;
 334     i->data = malloc(len);
 335     if (i->data == NULL && len != 0)
 336         return 0;
 337     i->length = len;
 338 
 339     if (RAND_bytes(i->data, i->length) != 1) {
 340         free(i->data);
 341         i->data = NULL;
 342         return 0;
 343     }
 344 
 345     {
 346         size_t j = len * 8;
 347         while(j > bits) {
 348             BN_clear_bit(bn, j - 1);
 349             j--;
 350         }
 351     }
 352 
 353     if (top == -1) {
 354         ;
 355     } else if (top == 0 && bits > 0) {
 356         BN_set_bit(bn, bits - 1);
 357     } else if (top == 1 && bits > 1) {
 358         BN_set_bit(bn, bits - 1);
 359         BN_set_bit(bn, bits - 2);
 360     } else {
 361         BN_clear(bn);
 362         return 0;
 363     }
 364 
 365     if (bottom && bits > 0)
 366         BN_set_bit(bn, 0);
 367 
 368     return 1;
 369 }
 370 
 371 /*
 372  *
 373  */
 374 
 375 int
 376 BN_uadd(BIGNUM *res, const BIGNUM *a, const BIGNUM *b)
     /* [<][>][^][v][top][bottom][index][help] */
 377 {
 378     const heim_integer *ai = (const heim_integer *)a;
 379     const heim_integer *bi = (const heim_integer *)b;
 380     const unsigned char *ap, *bp;
 381     unsigned char *cp;
 382     heim_integer ci;
 383     int carry = 0;
 384     ssize_t len;
 385 
 386     if (ai->negative && bi->negative)
 387         return 0;
 388     if (ai->length < bi->length) {
 389         const heim_integer *si = bi;
 390         bi = ai; ai = si;
 391     }
 392 
 393     ci.negative = 0;
 394     ci.length = ai->length + 1;
 395     ci.data = malloc(ci.length);
 396     if (ci.data == NULL)
 397         return 0;
 398 
 399     ap = &((const unsigned char *)ai->data)[ai->length - 1];
 400     bp = &((const unsigned char *)bi->data)[bi->length - 1];
 401     cp = &((unsigned char *)ci.data)[ci.length - 1];
 402 
 403     for (len = bi->length; len > 0; len--) {
 404         carry = *ap + *bp + carry;
 405         *cp = carry & 0xff;
 406         carry = (carry & ~0xff) ? 1 : 0;
 407         ap--; bp--; cp--;
 408     }
 409     for (len = ai->length - bi->length; len > 0; len--) {
 410         carry = *ap + carry;
 411         *cp = carry & 0xff;
 412         carry = (carry & ~0xff) ? 1 : 0;
 413         ap--; cp--;
 414     }
 415     if (!carry)
 416         memmove(cp, cp + 1, --ci.length);
 417     else
 418         *cp = carry;
 419 
 420     BN_clear(res);
 421     *((heim_integer *)res) = ci;
 422 
 423     return 1;
 424 }
 425 
 426 
 427 /*
 428  * Callback when doing slow generation of numbers, like primes.
 429  */
 430 
 431 void
 432 BN_GENCB_set(BN_GENCB *gencb, int (*cb_2)(int, int, BN_GENCB *), void *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 433 {
 434     gencb->ver = 2;
 435     gencb->cb.cb_2 = cb_2;
 436     gencb->arg = ctx;
 437 }
 438 
 439 int
 440 BN_GENCB_call(BN_GENCB *cb, int a, int b)
     /* [<][>][^][v][top][bottom][index][help] */
 441 {
 442     if (cb == NULL || cb->cb.cb_2 == NULL)
 443         return 1;
 444     return cb->cb.cb_2(a, b, cb);
 445 }

/* [<][>][^][v][top][bottom][index][help] */