Guest User

GMPBBS

a guest
Nov 4th, 2010
320
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.73 KB | None | 0 0
  1. /* gmpbbs.c: implementation code for the GMPBBS Blum Blum Shub PRNG
  2.  
  3.   Copyright 2005 Free Software Foundation.
  4.  
  5.   This file is released under the GPL.
  6.  
  7.   GMPBBS is free software; you can redistribute it and/or modify it
  8.   under the terms of the GNU General Public License as published by
  9.   the Free Software Foundation; either version 2 of the License,
  10.   or (at your option) any later version.
  11.  
  12.   GMPBBS is distributed in the hope that it will be useful, but
  13.   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14.   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15.   for more details.
  16.  
  17.   You should have received a copy of the GNU General Public License
  18.   along with GMPBBS; see the file LICENSE.  If not, write to
  19.   the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  20.   MA 02111-1307, USA.
  21.  
  22.   Contributed by Mark Rossmiller.
  23. */
  24.  
  25.  
  26. #include "gmpbbs.h"
  27.  
  28. #ifdef _WIN32
  29. /* no random device on windows as far as i know,
  30.    we get (strong?) random data from the operating system */
  31. int _hwrandread(unsigned char *rndbuf, size_t nbytes)
  32. #define FUNC_NAME "_hwrandread"
  33. {
  34.   HCRYPTPROV hp;
  35.   DWORD flags = CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET;
  36.  
  37.   if ( (! CryptAcquireContext( &hp, NULL, NULL, PROV_RSA_FULL, flags )) &&
  38.        ( GetLastError() != NTE_BAD_KEYSET ) )
  39.     {
  40.       flags |= CRYPT_NEWKEYSET;
  41.       if ( ! CryptAcquireContext( &hp, NULL, NULL, PROV_RSA_FULL, flags ) )
  42.     {
  43.       perror(FUNC_NAME ": CryptAcquireContext");
  44.       return(0);
  45.     }
  46.     }
  47.  
  48.   if (!CryptGenRandom(hp, nbytes, rndbuf))
  49.     {
  50.       CryptReleaseContext(hp, 0);
  51.       return(0);
  52.     }
  53.  
  54.   CryptReleaseContext(hp, 0);
  55.  
  56.   return(nbytes);  
  57. }
  58. #undef FUNC_NAME
  59. #define _urandread(x,y) _hwrandread(x,y)
  60. #else
  61. int _hwrandread(unsigned char *rndbuf, size_t nbytes)
  62. #define FUNC_NAME "_hwrandread"
  63. {
  64.   FILE *devrnd;
  65.   int nread;
  66.  
  67.   if ( (devrnd = fopen(HWRANDOM, "r")) == NULL)
  68.     {
  69.       perror(FUNC_NAME ": fopen");
  70.       return(0);
  71.     }
  72.   if ( (nread = fread(rndbuf, 1, nbytes, devrnd)) != nbytes)
  73.     {
  74.       perror(FUNC_NAME ": fread");
  75.     }
  76.  
  77.   fclose(devrnd);
  78.   return(nread);
  79. }
  80. #undef FUNC_NAME
  81. int _urandread(unsigned char *rndbuf, size_t nbytes)
  82. #define FUNC_NAME "_urandread"
  83. {
  84.   FILE *devrnd;
  85.   int nread;
  86.  
  87.   if ( (devrnd = fopen(URANDOM, "r")) == NULL)
  88.     {
  89.       perror(FUNC_NAME ": fopen");
  90.       return(0);
  91.     }
  92.   if ( (nread = fread(rndbuf, 1, nbytes, devrnd)) != nbytes)
  93.     {
  94.       perror(FUNC_NAME ": fread");
  95.     }
  96.  
  97.   fclose(devrnd);
  98.   return(nread);
  99. }
  100. #undef FUNC_NAME
  101. #endif
  102.  
  103. /*
  104.   initialize bbs->blumint randomly
  105.     key_bitlen may be over by n=pq,
  106.     so the actual keylen may be 1 bit more than requested...
  107.     to modify it, you'd have to set high bit and clear second high bit for p,q.
  108.     (and hope they don't bump up after we find their real values
  109.     at any rate, it's not a big deal really.. just confusing :)
  110. */
  111. int rndbbs_gen_blumint (rndbbs_t *bbs, unsigned int key_bitlen)
  112. #define FUNC_NAME "rndbbs_gen_blumint"
  113. {
  114.   mpz_t p, q;
  115.  
  116.   if (key_bitlen < GMPBBS_MINKEYLEN)
  117.     return(0);
  118.  
  119.   /* init pstr */
  120.   {
  121.     int i, pbits = (key_bitlen)/2 + 1;
  122.     int pbytes = ceil(pbits/8.0);
  123.     char *pstr;
  124.     unsigned char *rnd;
  125.  
  126.     if ( (rnd = (unsigned char *) malloc(pbytes)) == NULL )
  127.       {
  128.     perror(FUNC_NAME ": malloc");
  129.     return(0);
  130.       }
  131.  
  132.     /* get random seed for p from random device */
  133.     if (_hwrandread(rnd, pbytes) != pbytes)
  134.       {
  135.     free(rnd);
  136.     perror(FUNC_NAME ": _hwrandread");
  137.     return(0);
  138.       }
  139.  
  140.     if ( pbits % 8 )
  141.       /* a little bit-fiddling to get *exactly* our number of bits */
  142.       /* then set the high bit all in one pass */
  143.       rnd[0] = ( ( rnd[0] & ~( ~0 << (pbits % 8) ) ) |
  144.          ( 0x80 >> ( 8 - (pbits%8) ) ) );
  145.     else
  146.       /* just set high bit */
  147.       rnd[0] |= 0x80;
  148.  
  149.     if ( (pstr = (char *) malloc(2*pbytes+1)) == NULL)
  150.       {
  151.     free(rnd);
  152.     perror(FUNC_NAME ": malloc");
  153.     return(0);
  154.       }
  155.     for (i=0;i<pbytes;i++)
  156.       {
  157.     snprintf(pstr+(2*i), 3, "%02x", rnd[i]);
  158.       }
  159.     free(rnd);
  160.  
  161.     if (mpz_init_set_str(p, pstr, 16) == -1)
  162.       {
  163.     free(pstr);
  164.     perror(FUNC_NAME ": mpz_init_set_str");
  165.     return(0);
  166.       }
  167.     free(pstr);
  168.  
  169.     /* now, find p such that ( p prime ) && ( p = 3 (mod 4) ) */
  170.     for(;;)
  171.       {
  172.     mpz_nextprime(p,p);
  173.  
  174.     /* mpz_tstbit(p, 1) (p!=2) is faster than mpz_fdiv_ui(p, 4)==3 */
  175.     if ( mpz_tstbit(p, 1) &&
  176.          /* probab_prime: mainly to do an advanced check (higher REPS) */
  177.          mpz_probab_prime_p(p, MPZ_PROBAB_PRIME_REPS) )
  178.       break;
  179.       }
  180.   }
  181.  
  182.   /* init qstr */
  183.   {
  184.     int i, qbits = (key_bitlen)/2 + (key_bitlen%2);
  185.     int qbytes = ceil(qbits/8.0);
  186.  
  187.     char *qstr;
  188.     unsigned char *rnd;
  189.  
  190.     if ( (rnd = (unsigned char *) malloc(qbytes)) == NULL )
  191.       {
  192.     perror(FUNC_NAME ": malloc");
  193.     return(0);
  194.       }
  195.  
  196.     /* get random seed for q from random device */
  197.     if (_hwrandread(rnd, qbytes) != qbytes)
  198.       {
  199.     free(rnd);
  200.     perror(FUNC_NAME ": _hwrandread");
  201.     return(0);
  202.       }
  203.  
  204.     if ( qbits % 8 )
  205.       /* a little bit-fiddling to get *exactly* our number of bits */
  206.       /* then set the high bit all in one pass */
  207.       rnd[0] = ( ( rnd[0] & ~( ~0 << (qbits % 8) ) ) |
  208.          ( 0x80 >> ( 8 - (qbits%8) ) ) );
  209.     else
  210.       /* just set high bit */
  211.       rnd[0] |= 0x80;
  212.  
  213.     if ( (qstr = (char *) malloc(2*qbytes+1)) == NULL)
  214.       {
  215.     free(rnd);
  216.     perror(FUNC_NAME ": malloc");
  217.     return(0);
  218.       }
  219.     for (i=0;i<qbytes;i++)
  220.       {
  221.     snprintf(qstr+(2*i), 3, "%02x", rnd[i]);
  222.       }
  223.     free(rnd);
  224.  
  225.     if (mpz_init_set_str(q, qstr, 16) == -1)
  226.       {
  227.     free(qstr);
  228.     perror(FUNC_NAME ": mpz_init_set_str");
  229.     return(0);
  230.       }
  231.     free(qstr);
  232.  
  233.     /* now, find q such that ( q prime ) && ( q = 3 (mod 4) ) */
  234.     for(;;)
  235.       {
  236.     mpz_nextprime(q,q);
  237.     /* mpz_tstbit(q, 1) (q!=2) is faster than mpz_fdiv_ui(q, 4)==3 */
  238.     if ( mpz_tstbit(q, 1) &&
  239.          /* probab_prime: mainly to do an advanced check (higher REPS) */
  240.          mpz_probab_prime_p(q, MPZ_PROBAB_PRIME_REPS) )
  241.       break;
  242.       }
  243.   }
  244.  
  245.   /* a blum integer is p*q ( p and q both = 3 (mod 4) ) */
  246.   mpz_mul(bbs->blumint, p, q);
  247.  
  248.   /* we need this later to find how many bits ( log2(bbs->key_bitlen) ) */
  249.   bbs->key_bitlen = mpz_sizeinbase(bbs->blumint, 2);
  250.  
  251.   /* we want p,q if we're going to use this as a stream cipher */
  252.  
  253.   mpz_clear(p);
  254.   mpz_clear(q);
  255.  
  256.   return(1);
  257. }
  258. #undef FUNC_NAME
  259.  
  260. /* initialize bbs->x randomly */
  261. int rndbbs_gen_x (rndbbs_t *bbs)
  262. #define FUNC_NAME "rndbbs_gen_x"
  263. {
  264.   unsigned char *rnd;
  265.   char *xstr;
  266.   int i, nbytes = (mpz_sizeinbase(bbs->blumint, 2)+7)/8;
  267.  
  268.   if ( (rnd = (unsigned char *) malloc(nbytes)) == NULL )
  269.     {
  270.       perror(FUNC_NAME ": malloc");
  271.       return(0);
  272.     }
  273.  
  274.   /* get random seed for x from random device */
  275.   if (_hwrandread(rnd, nbytes) != nbytes)
  276.     {
  277.       free(rnd);
  278.       perror(FUNC_NAME ": _hwrandread");
  279.       return(0);
  280.     }
  281.  
  282.   if ( (xstr = (char *) malloc(2*nbytes+1)) == NULL)
  283.     {
  284.       free(rnd);
  285.       perror(FUNC_NAME ": malloc");
  286.       return(0);
  287.     }
  288.   for (i=0;i<nbytes;i++)
  289.     {
  290.       snprintf(xstr+2*i, 3, "%02x", rnd[i]);
  291.     }
  292.   free(rnd);
  293.  
  294.   if (mpz_set_str(bbs->x, xstr, 16) == -1)
  295.     {
  296.       free(xstr);
  297.       perror(FUNC_NAME ": mpz_set_str");
  298.       return(0);
  299.     }
  300.   free(xstr);
  301.  
  302.   /* now, find x such that gcd(blumint,x) = 1. */
  303.   {
  304.     mpz_t tmpgcd;
  305.  
  306.     mpz_init(tmpgcd);
  307.     for(;;)
  308.       {
  309.     mpz_gcd(tmpgcd, bbs->blumint, bbs->x);
  310.     if (mpz_cmp_ui(tmpgcd, 1) == 0)
  311.       break;
  312.     mpz_add_ui(bbs->x, bbs->x, 1);
  313.       }
  314.     mpz_clear(tmpgcd);
  315.   }
  316.  
  317.   /* x[0] = x^2 (mod blumint) */
  318.   mpz_powm_ui(bbs->x, bbs->x, 2, bbs->blumint);
  319.  
  320.   return(1);
  321. }
  322. #undef FUNC_NAME
  323.  
  324. rndbbs_t *rndbbs_new()
  325. #define FUNC_NAME "rndbbs_new"
  326. {
  327.   rndbbs_t *bbs = NULL;
  328.  
  329.   if ( (bbs = (rndbbs_t *) malloc( sizeof(rndbbs_t) ) ) == NULL )
  330.     {
  331.       perror(FUNC_NAME ": malloc");
  332.       return(NULL);
  333.     }
  334.  
  335.   mpz_init(bbs->blumint);
  336.   mpz_init(bbs->x);
  337.   bbs->key_bitlen = 0;
  338.   bbs->improved = 1;
  339.   bbs->xor_urandom = 0;
  340.  
  341.   return(bbs);
  342. }
  343. #undef FUNC_NAME
  344.  
  345. int rndbbs_destroy(rndbbs_t *bbs)
  346. #define FUNC_NAME "rndbbs_destroy"
  347. {
  348.   /* if using this as a cipher, we need to append xn+1 to the end. */
  349.   mpz_clear(bbs->blumint);
  350.   mpz_clear(bbs->x);
  351.   free(bbs);
  352.  
  353.   return(1);
  354. }
  355. #undef FUNC_NAME
  356.  
  357. char *rndbbs_randbytes(rndbbs_t *bbs, size_t nbytes)
  358. #define FUNC_NAME "rndbbs_randbytes"
  359. {
  360.   char *retbuf;
  361.   char *urandom_buffer = NULL;
  362.  
  363.   if ( (retbuf = (char *) malloc(nbytes)) == NULL)
  364.     {
  365.       perror(FUNC_NAME ": malloc");
  366.       return(NULL);
  367.     }
  368.  
  369.   if ( bbs->xor_urandom )
  370.     {
  371.       if ( (urandom_buffer = (char *) malloc(nbytes)) == NULL)
  372.     {
  373.       perror(FUNC_NAME ": malloc");
  374.       return(NULL);
  375.     }
  376.  
  377.       if ( _urandread(urandom_buffer, nbytes) != nbytes )
  378.     {
  379.       perror(FUNC_NAME ": _urandread: continuting...");
  380.       bbs->xor_urandom = 0;
  381.     }
  382.     }
  383.  
  384.   memset(retbuf, 0, nbytes);
  385.  
  386.   if (!bbs->improved)
  387.     {
  388.       /* basic implementation without improvements (only keep parity) */
  389.       {
  390.     int i;
  391.     for (i=0;i<nbytes;i++)
  392.       {
  393.         int j;
  394.  
  395.         /* we keep the parity (least significant bit) of each x_n */
  396.         for (j=7;j>=0;j--)
  397.           {
  398.         /* x[n+1] = x[n]^2 (mod blumint) */
  399.         mpz_powm_ui(bbs->x, bbs->x, 2, bbs->blumint);
  400.  
  401.         /* mpz_fdiv_ui(bbs->x, 2) == mpz_tstbit(bbs->x, 0) */
  402.         retbuf[i] |= (mpz_tstbit(bbs->x, 0) << j);
  403.           }
  404.         if (bbs->xor_urandom)
  405.           retbuf[i] ^= urandom_buffer[i];
  406.       }
  407.     if ( urandom_buffer != NULL )
  408.       free(urandom_buffer);
  409.     return(retbuf);
  410.       }
  411.     }
  412.   else
  413.     {
  414.       /* improved implementation (keep log2(log2(blumint)) bits of x[i]) */
  415.       unsigned int loglogblum = log(1.0*bbs->key_bitlen)/log(2.0);
  416.  
  417.       unsigned int byte=0, bit=0, i;
  418.  
  419.       for (;;)
  420.     {
  421.       /* x[n+1] = x[n]^2 (mod blumint) */
  422.       mpz_powm_ui(bbs->x, bbs->x, 2, bbs->blumint);
  423.  
  424.       for (i=0;i<loglogblum;i++)
  425.         {
  426.           if (byte == nbytes)
  427.         {
  428.           if ( urandom_buffer != NULL )
  429.             free(urandom_buffer);
  430.           return(retbuf);
  431.         }
  432.  
  433.           /* get the ith bit of x */
  434.           retbuf[byte] |= (mpz_tstbit(bbs->x, i) << (7-bit) );
  435.  
  436.           if (bit == 7)
  437.         {
  438.           if (bbs->xor_urandom)
  439.             retbuf[byte] ^= urandom_buffer[byte];
  440.           byte++;
  441.           bit=0;
  442.         }
  443.           else
  444.         {
  445.           bit++;
  446.         }
  447.         }
  448.     }
  449.     }
  450. }
  451. #undef FUNC_NAME
  452.  
  453. unsigned int *rndbbs_randint(rndbbs_t *bbs, unsigned int base, size_t nmemb)
  454. #define FUNC_NAME "rndbbs_randint"
  455. {
  456.   int i;
  457.   unsigned char *rndbuf;
  458.   char *mpzstr;
  459.   mpz_t bn;
  460.   unsigned int *rndint = NULL;
  461.  
  462.   /* we waste a few precious bits here unless we're a power of 256 */
  463.   unsigned int nbytes = ceil((nmemb)*log(base)/log(256));
  464.  
  465.   rndbuf = (unsigned char *) rndbbs_randbytes(bbs, nbytes);
  466.  
  467.   if ( (mpzstr = (char *) malloc(2*nbytes+1)) == NULL)
  468.     {
  469.       free(rndbuf);
  470.       perror(FUNC_NAME ": malloc");
  471.       return(NULL);
  472.     }
  473.   for (i=0;i<nbytes;i++)
  474.     {
  475.       snprintf(mpzstr+2*i, 3, "%02x", rndbuf[i]);
  476.     }
  477.   free(rndbuf);
  478.  
  479.   if (mpz_init_set_str(bn, mpzstr, 16) == -1)
  480.     {
  481.       free(mpzstr);
  482.       perror(FUNC_NAME ": mpz_set_str");
  483.       return(NULL);
  484.     }
  485.   free(mpzstr);
  486.  
  487.   if ((rndint = (unsigned int *) malloc(nmemb * sizeof(unsigned int))) == NULL)
  488.     {
  489.       mpz_clear(bn);
  490.       perror(FUNC_NAME ": malloc");
  491.       return(NULL);
  492.     }
  493.  
  494.   for (i=0;i<nmemb+1;i++)
  495.     {
  496.       mpz_t tmpmpz;
  497.       mpz_t q;
  498.  
  499.       mpz_init(q);
  500.       mpz_init_set_ui(tmpmpz, base);
  501.       mpz_pow_ui(tmpmpz, tmpmpz, (nmemb-i) );
  502.       mpz_tdiv_q(q, bn, tmpmpz);
  503.       if (i>0)
  504.     rndint[i-1] = mpz_get_ui(q);
  505.  
  506.       mpz_mul(tmpmpz, q, tmpmpz);
  507.       mpz_sub(bn, bn, tmpmpz);
  508.  
  509.       mpz_clear(q);
  510.       mpz_clear(tmpmpz);
  511.     }
  512.   mpz_clear(bn);
  513.  
  514.   return(rndint);
  515. }
  516. #undef FUNC_NAME
Advertisement
Add Comment
Please, Sign In to add comment