pike.git / src / post_modules / Nettle / nettle.cmod

version» Context lines:

pike.git/src/post_modules/Nettle/nettle.cmod:1:   /* nettle.cmod -*- c -*- */    - #include "global.h" + #include "module.h"   #include "interpret.h" - #include "svalue.h" - /* For this_object() */ - #include "object.h" +    #include "operators.h"   #include "module_support.h"   #include "threads.h" - #include "pike_memory.h" +    #include "pike_cpulib.h"   #include "bignum.h"   #include "sprintf.h"      #include "nettle_config.h"      #ifdef HAVE_LIBNETTLE      #include "nettle.h"      #include <nettle/yarrow.h> -  + #include <nettle/memxor.h>      #ifdef HAVE_NETTLE_VERSION_H   #include <nettle/version.h>   #endif      DECLARATIONS      /*! @module Nettle    *! Low level crypto functions used by the @[Crypto] module. Unless    *! you are doing something very special, you would want to use the
pike.git/src/post_modules/Nettle/nettle.cmod:66:    *! internal state of 256 bits.    */   PIKECLASS Yarrow   program_flags PROGRAM_CLEAR_STORAGE;   {    CVAR struct yarrow256_ctx ctx;    CVAR struct yarrow_source *sources;       DECLARE_STORAGE;    -  /*! @decl void create(void|int sources) +  /*! @decl void create(void|int(0..) sources)    *! The number of entropy sources that will feed entropy to the    *! random number generator is given as an argument to Yarrow    *! during instantiation.    *! @seealso    *! @[update]    */ -  PIKEFUN void create(void|int arg) +  PIKEFUN void create(void|int(0..) arg)    flags ID_PROTECTED;    {    INT32 num = 0;       if(arg) { -  if (TYPEOF(*arg) != PIKE_T_INT) -  Pike_error("Bad argument type.\n"); +     num = arg->u.integer;    if(num < 0)    Pike_error("Invalid number of sources.\n");    free (THIS->sources); -  +  if( num > 0 )    THIS->sources = xalloc(sizeof(struct yarrow_source)*num); -  +  else +  THIS->sources = NULL; +  pop_stack();    }    else    {    free (THIS->sources);    THIS->sources = NULL;    }    yarrow256_init(&THIS->ctx, num, THIS->sources);    }       /*! @decl Yarrow seed(string(0..255) data)
pike.git/src/post_modules/Nettle/nettle.cmod:200:    /*! @decl int(0..) needed_sources()    *! The number of sources that must reach the threshold before a    *! slow reseed will happen.    */    PIKEFUN int(0..) needed_sources()    optflags OPT_EXTERNAL_DEPEND;    {    RETURN yarrow256_needed_sources(&THIS->ctx);    }    -  /*! @decl string(0..255) random_string(int length) +  /*! @decl string(0..255) random_string(int(0..) length)    *! Returns a pseudo-random string of the requested @[length].    */ -  PIKEFUN string(0..255) random_string(int length) +  PIKEFUN string(0..255) random_string(int(0..) length)    optflags OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT;    {    struct pike_string *rnd;    if(length < 0)    Pike_error("Invalid length, must be positive.\n");    if( !yarrow256_is_seeded(&THIS->ctx) )    Pike_error("Random generator not seeded.\n");    rnd = begin_shared_string(length);    yarrow256_random(&THIS->ctx, length, (uint8_t *)rnd->str);    RETURN end_shared_string(rnd);
pike.git/src/post_modules/Nettle/nettle.cmod:319:    INCREMENT(16, THIS->ctr);    }       /*! @decl string(8bit) random_string(int(0..) len)    *!    *! Generates @[len] amount of pseudo random data. In contrast with    *! the Fortuna PseudoRandomData function, which only allows 2^20    *! bytes of random data per call, the necessary rekey operations    *! are here performed internally, so no such restrictions apply.    */ -  PIKEFUN string(8bit) random_string(int len) +  PIKEFUN string(8bit) random_string(int(0..) len)    {    int stored = 0; -  +  struct pike_string *s; +  uint8_t *str;       if(len<0) Pike_error("Length has to be positive.\n"); -  struct pike_string *s = begin_shared_string(len); -  uint8_t *str = (uint8_t *)s->str; +  +  s = begin_shared_string(len); +  str = (uint8_t *)s->str; +     while( (len-stored) >= 16 )    {    fortuna_generate(str);    stored += 16;    str += 16;       if( !(stored % (1<<20)) )    fortuna_rekey();    }   
pike.git/src/post_modules/Nettle/nettle.cmod:363:    sha256_init(&THIS->sha_ctx);    }       EXIT    gc_trivial;    {    free(THIS->ctr);    free(THIS->key);    }   } + /*! @endclass +  */    -  + /*! @class AES128_CTR_DRBG +  *! +  *! Minimal implementation of NIST SP800-90Ar1 pseudo random number +  *! generator CTR_DRBG using AES-128. No personalization, nounces or +  *! additional data are supported. +  *! +  *! @seealso +  *! @[Random.AES128_CTR_DRBG] +  */ + PIKECLASS AES128_CTR_DRBG + program_flags PROGRAM_CLEAR_STORAGE; + { +  CVAR struct aes_ctx aes_ctx; +  CVAR uint8_t *key; +  CVAR uint8_t *ctr; +  CVAR INT64 reseed_counter; +  CVAR INT64 reseed_interval; +  +  DECLARE_STORAGE; +  +  /* +  * blocklen = 128 +  * ctr_len = 128 +  * keylen = 128 +  * seedlen = 256 +  * reseed_interval = 2**48 +  */ +  + #ifndef AES128_KEY_SIZE + #define AES128_KEY_SIZE (128>>3) + #endif +  +  static void ctr_debug_update(char *data) +  { +  uint8_t tmp_key[16]; +  INCREMENT(16, THIS->ctr); +  aes_encrypt(&THIS->aes_ctx, 16, tmp_key, THIS->ctr); +  INCREMENT(16, THIS->ctr); +  aes_encrypt(&THIS->aes_ctx, 16, THIS->ctr, THIS->ctr); +  memcpy(THIS->key, tmp_key, 16); +  if( data ) +  { +  memxor(THIS->key, (uint8_t*)data, 16); +  memxor(THIS->ctr, (uint8_t*)data+16, 16); +  } +  aes_set_encrypt_key(&THIS->aes_ctx, AES128_KEY_SIZE, THIS->key); +  } +  +  /*! @decl void reseed(string(8bit) data) +  *! Updated the internal key with the provided additional entropy. +  */ +  PIKEFUN void reseed(string(8bit) data) +  { +  if( data->len!=32 ) +  Pike_error("Illegal entropy size.\n"); +  NO_WIDE_STRING(data); +  ctr_debug_update(data->str); +  THIS->reseed_counter = 1; +  } +  +  /*! @decl int(1..281474976710656) reseed_interval +  *! The number of times @[random_string] can be called before a +  *! reseeding is forced. The number needs to be in the range of +  *! 1..1<<48. +  *! +  *! @seealso +  *! @[entropy_underflow] +  */ +  PIKEFUN void `reseed_interval=(int(1..281474976710656) interval) +  { +  INT64 interval_int64 = interval; +  if( interval_int64 < 1 || interval_int64 > (((INT64)1)<<48) ) +  Pike_error("Interval out of range.\n"); +  THIS->reseed_interval = interval_int64; +  } +  +  /*! @decl int(1..281474976710656) reseed_interval +  *! The number of times @[random_string] can be called before a +  *! reseeding is forced. The number needs to be in the range of +  *! 1..1<<48. +  *! +  *! @seealso +  *! @[entropy_underflow] +  */ +  PIKEFUN void `reseed_interval=(object(Gmp.mpz) interval) +  { +  INT64 interval_int64 = 0; +  if (!low_int64_from_bignum(&interval_int64, interval)) +  Pike_error("Invalid interval.\n"); +  if( interval_int64 < 1 || interval_int64 > (((INT64)1)<<48) ) +  Pike_error("Interval out of range.\n"); +  THIS->reseed_interval = interval_int64; +  } +  +  PIKEFUN int `reseed_interval() +  { +  push_int64(THIS->reseed_interval); +  } +  +  /*! @decl void entropy_underflow() +  *! Called when @[random_string] has been called more than +  *! @[reseed_interval] times. +  */ +  PIKEFUN void entropy_underflow() +  flags ID_PROTECTED; +  { +  Pike_error("Requires reseed.\n"); +  } +  +  /*! @decl string(8bit) random_string(int(0..) len) +  *! +  *! Generates @[len] amount of pseudo random data. Does not allow +  *! for additional input data in the call. +  */ +  PIKEFUN string(8bit) random_string(int(0..) len) +  { +  int stored = 0; +  struct pike_string *s; +  uint8_t *str; +  +  if(len<0) Pike_error("Length has to be positive.\n"); +  if(THIS->reseed_counter>THIS->reseed_interval) +  apply_current(f_Nettle_AES128_CTR_DRBG_entropy_underflow_fun_num, 0); +  +  s = begin_shared_string(len); +  str = (uint8_t *)s->str; +  +  while( (len-stored) >= 16 ) +  { +  INCREMENT(16, THIS->ctr); +  aes_encrypt(&THIS->aes_ctx, 16, str, THIS->ctr); +  stored += 16; +  str += 16; +  +  if( !(stored % (1<<19)) ) +  { +  ctr_debug_update(NULL); +  THIS->reseed_counter++; +  if(THIS->reseed_counter>THIS->reseed_interval) +  apply_current(f_Nettle_AES128_CTR_DRBG_entropy_underflow_fun_num, 0); +  } +  } +  +  if( len>stored ) +  { +  uint8_t buf[16]; +  INCREMENT(16, THIS->ctr); +  aes_encrypt(&THIS->aes_ctx, 16, buf, THIS->ctr); +  memcpy(str, buf, len-stored); +  } +  +  ctr_debug_update(NULL); +  THIS->reseed_counter++; +  +  RETURN end_shared_string(s); +  } +  +  INIT +  { +  THIS->ctr = xcalloc(1,16); +  THIS->key = xcalloc(1,16); +  THIS->reseed_counter = 1; +  THIS->reseed_interval = ((INT64)1)<<48; +  aes_set_encrypt_key(&THIS->aes_ctx, AES128_KEY_SIZE, THIS->key); +  } +  +  EXIT +  gc_trivial; +  { +  free(THIS->ctr); +  free(THIS->key); +  } + } +    /*! @endclass    */      /*! @decl int(0..) rsa_unpad(string(0..255) data, int(1..2) type)    *!    *! Unpads a message that has been padded according to    *! RSAES-PKCS1-V1_5-ENCODE(message) in PKCS#1 v2.2, but without the    *! null byte prefix. The padding method used on the original message    *! must be provided in the @[type] parameter. All content dependent    *! processing is done in constant time for the same padding type and    *! @[data] length.    *!    *! @returns    *! Returns the position in the string where the first non-padding    *! character is, or 0.    */ - PIKEFUN int(0..) rsa_unpad(string(0..255) data, int type) + PIKEFUN int(0..) rsa_unpad(string(0..255) data, int(1..2) type)   {    int i, pad=0, nonpad=0, pos=0;    unsigned char *str;       NO_WIDE_STRING(data);       /* Indata is smaller than minimum size, so we can exit immediately    without timing issue. 1 type + 8 padding + 1 delimiter + 1 value    = 11 bytes. */    if(data->len < 11 ) RETURN 0;
pike.git/src/post_modules/Nettle/nettle.cmod:423:         /*! @decl string(0..127) crypt_md5(string(0..255) password, @    *! string(0..255) salt,@    *! void|string(0..255) magic)    *! Does the crypt_md5 abrakadabra (MD5 + snakeoil). It is assumed    *! that @[salt] does not contain "$".    *!    *! The @[password] memory will be cleared before released.    */ - PIKEFUN string(0..127) crypt_md5(string(0..255) pw, string(0..255) salt, -  void|string(0..255) magic) + PIKEFUN string(0..127) crypt_md5(string pw, string salt, +  void|string magic)    optflags OPT_TRY_OPTIMIZE; -  +  /* NB: We use a weaker type above to allow us to delay +  * throwing errors on wide strings until we've had +  * time to censor the password string. +  */ +  rawtype tFunc(tStr8 tStr8 tOr(tStr8, tVoid), tStr7);   {    char *hash; -  +  +  /* Censor the password. */ +  push_string(pw); +  args++; +  add_ref(Pike_sp[-args].u.string = MK_STRING("censored")); +     NO_WIDE_STRING(pw);    NO_WIDE_STRING(salt);       pw->flags |= STRING_CLEAR_ON_EXIT;       if(!magic)    {    hash = pike_crypt_md5(pw->len, pw->str, salt->len, salt->str,    3, "$1$");    }
pike.git/src/post_modules/Nettle/nettle.cmod:452:    magic->len, magic->str);    }       push_text(hash);   }      #ifdef HAVE_CRC32_INTRINSICS   static int supports_sse42 = 0;      static ATTRIBUTE((target("sse4"))) -  unsigned int intel_crc32c(const unsigned int *p, size_t len) +  unsigned int intel_crc32c(const unsigned int *p, size_t len, +  unsigned int h)   { -  unsigned int h=0xffffffff; +     const unsigned int *e = p + (len>>2);    const unsigned char *c = (const unsigned char*)e; -  +  h = ~h;       /* .. all full integers .. */    while( p<e )    h = __builtin_ia32_crc32si(h, *(p++));       len &= 3;       /* any remaining bytes. */    while( len-- )    h = __builtin_ia32_crc32qi(h, *(c++));    -  return h ^ 0xffffffff; +  return ~h;   }   #endif /* HAVE_CRC32_INTRINSICS */      /* Copyright 2001, D. Otis. Use this program, code or tables */   /* extracted from it, as desired without restriction. */   static const INT32 crc[256] = {    0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,    0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,    0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,    0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
pike.git/src/post_modules/Nettle/nettle.cmod:541:    0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,    0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,    0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,    0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,    0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,    0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,    0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,    0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351,   };    - /*! @decl int(0..) crc32c(string(8bit) data) + /*! @decl int(0..) crc32c(string(8bit) data, void|int(0..) seed)    *! Implements the Castagnoli CRC, CRC32C. Hardware optimized on Intel    *! CPUs with SSE 4.2. -  +  *! +  *! @param seed +  *! Can be fed with the result of the previous invocation to chain on new data. +  *! Defaults to zero on virgin runs.    */ - PIKEFUN int(0..) crc32c(string(8bit) data) + PIKEFUN int(0..) crc32c(string(8bit) data, void|int(0..) seed)   { -  +  unsigned int h = 0; +  if(seed) +  h = seed->u.integer; +    #ifdef HAVE_CRC32_INTRINSICS    if(supports_sse42)    { -  push_int64(intel_crc32c((const unsigned int *)data->str, data->len)); +  push_int64(intel_crc32c((const unsigned int *)data->str, data->len, h));    }    else   #endif /* HAVE_CRC32_INTRISINCS */    { -  unsigned int h=0xffffffff, i=0; -  for(; i<data->len; i++) +  unsigned int i=0, len = data->len; +  for(h = ~h; i<len; i++)    h = (h>>8)^crc[(h^data->str[i])&0xFF]; -  push_int64(h ^ 0xffffffff); +  push_int64(~h);    }   }      /*! @endmodule    */      #endif /* HAVE_LIBNETTLE */      PIKE_MODULE_INIT   {