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

version» Context lines:

pike.git/src/post_modules/Nettle/nettle.cmod:63:   #ifndef HAVE_STRUCT_YARROW256_CTX_SEED_FILE    static void pike_generate_seed_file(void)    {    struct pike_string *seed_file =    begin_shared_string(YARROW256_SEED_FILE_SIZE);    yarrow256_random(&THIS->ctx, YARROW256_SEED_FILE_SIZE, STR0(seed_file));    if (THIS->seed_file) {    free_string(THIS->seed_file);    }    THIS->seed_file = end_shared_string(seed_file); -  THIS->seed_file->flags |= STRING_CLEAR_ON_EXIT; +     }   #else   #define pike_generate_seed_file()   #endif       /*! @decl void create(void|int 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
pike.git/src/post_modules/Nettle/nettle.cmod:99:    }    else    {    free (THIS->sources);    THIS->sources = NULL;    }    yarrow256_init(&THIS->ctx, num, THIS->sources);    }       /*! @decl Yarrow seed(string data) -  *! The random generator needs to be seeded before -  *! it can be used. The seed must be at least 32 -  *! characters long. The seed could be stored from -  *! a previous run by inserting the value returned -  *! from @[get_seed]. +  *! +  *! The random generator needs to be seeded before it can be used. +  *! The seed must be at least 32 characters long. The seed could be +  *! stored from a previous run by inserting the value returned from +  *! @[get_seed]. +  *!    *! @returns    *! Returns the called object.    *! @seealso    *! @[min_seed_size], @[get_seed], @[is_seeded]    */    PIKEFUN object seed(string data)    optflags OPT_SIDE_EFFECT;    {    if(data->len < YARROW256_SEED_FILE_SIZE)    Pike_error("Seed must be at least %d characters.\n",    YARROW256_SEED_FILE_SIZE);       NO_WIDE_STRING(data); -  data->flags |= STRING_CLEAR_ON_EXIT; +     yarrow256_seed(&THIS->ctx, data->len, STR0(data));    pike_generate_seed_file();    RETURN this_object();    }       /*! @decl int(0..) min_seed_size()    *! Returns the minimal number of characters that the @[seed]    *! needs to properly seed the random number generator.    *! @seealso    *! @[seed]
pike.git/src/post_modules/Nettle/nettle.cmod:146:    *! Returns part of the internal state so that it can    *! be saved for later seeding.    *!    *! @seealso    *! @[seed()], @[random_string()]    */    PIKEFUN string(0..255) get_seed()    optflags OPT_EXTERNAL_DEPEND;    rawtype tDeprecated(tFunc(tNone, tStr8));    { -  struct pike_string * ret; +     if( !yarrow256_is_seeded(&THIS->ctx) )    Pike_error("Random generator not seeded.\n");      #ifdef HAVE_STRUCT_YARROW256_CTX_SEED_FILE -  ret = make_shared_binary_string(THIS->ctx.seed_file, +  RETURN make_shared_binary_string(THIS->ctx.seed_file,    YARROW256_SEED_FILE_SIZE); -  ret->flags |= STRING_CLEAR_ON_EXIT; -  RETURN ret; +    #else    if (THIS->seed_file) {    REF_RETURN THIS->seed_file;    } else {    /*    * It seems somewhat unreasonable to use uninitialized memory here.    * Instead, I think the user should be warned. It really isnt a very    * good source of entropy and may lead to undefined behavior in C.    * Why not simply return 0 in that case?    * /arne    */    struct pike_string *s = begin_shared_string(YARROW256_SEED_FILE_SIZE);    PIKE_MEM_RW_RANGE(s->str, YARROW256_SEED_FILE_SIZE);    s = end_shared_string(s); -  s->flags |= STRING_CLEAR_ON_EXIT; +     RETURN s;    }   #endif /* HAVE_STRUCT_YARROW256_CTX_SEED_FILE */    }       /*! @decl int(0..1) is_seeded()    *! Returns 1 if the random generator is seeded and ready    *! to generator output. 0 otherwise.    *! @seealso    *! @[seed]
pike.git/src/post_modules/Nettle/nettle.cmod:222:    *!    *! @seealso    *! @[create]    */    PIKEFUN int(0..1) update(string data, int source, int entropy)    optflags OPT_SIDE_EFFECT;    {    int ret;    /* FIXME: Wide strings could actually be supported here */    NO_WIDE_STRING(data); -  data->flags |= STRING_CLEAR_ON_EXIT; +     if( !THIS->sources )    Pike_error("This random generator has no sources.\n");    if( source<0 || (unsigned)source>=THIS->ctx.nsources )    Pike_error("Invalid random source.\n");    if( entropy<0 )    Pike_error("Entropy must be positive.\n");    if( entropy>(data->len*8) )    Pike_error("Impossibly large entropy value.\n");    ret = yarrow256_update(&THIS->ctx, source, entropy, data->len,    (const uint8_t *)data->str);
pike.git/src/post_modules/Nettle/nettle.cmod:262:    PIKEFUN string(0..255) random_string(int 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); -  rnd = end_shared_string(rnd); -  rnd->flags |= STRING_CLEAR_ON_EXIT; -  RETURN rnd; +  RETURN end_shared_string(rnd);    }       INIT    {    THIS->sources = NULL;    yarrow256_init(&THIS->ctx, 0, NULL);    }       EXIT    gc_trivial;
pike.git/src/post_modules/Nettle/nettle.cmod:288:    free(THIS->sources);    }    }   }      /*! @endclass    */      /*! @decl string(0..127) crypt_md5(string password, string salt,@    *! void|string magic) -  *! Does the crypt_md5 abrakadabra (MD5 + snakeoil). -  *! It is assumed that @[salt] does not contain "$". +  *! 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 pw, string salt, void|string magic)    optflags OPT_TRY_OPTIMIZE;   {    char *hash;    NO_WIDE_STRING(pw);    NO_WIDE_STRING(salt);       pw->flags |= STRING_CLEAR_ON_EXIT;   
pike.git/src/post_modules/Nettle/nettle.cmod:469:    }       for(i=0; i < block_size; i++)    dest[i] = THIS->iv[i] ^ Pike_sp[-1].u.string->str[i];       pop_stack();    MEMCPY(THIS->iv, source, block_size);    }       /*! @decl void create(program|object|function cipher, mixed ... args) +  *!    *! Initialize the CBC wrapper with a cipher algorithm. If it is a -  *! program, an object will be instantiated with @[args] as arguments. -  *! If it is an object that doesn't conform to the cipher API, but has -  *! an @[LFUN::`()], that LFUN will be called. If it is a function, -  *! that function will be called with @[args] as arguments. +  *! program, an object will be instantiated with @[args] as +  *! arguments. If it is an object that doesn't conform to the cipher +  *! API, but has an @[LFUN::`()], that LFUN will be called. If it is +  *! a function, that function will be called with @[args] as +  *! arguments.    */    PIKEFUN void create(program|object|function cipher, mixed ... more)    flags ID_PROTECTED;    {    int old_block_size = THIS->block_size;    THIS->object = make_cipher_object(args);       safe_apply(THIS->object, "block_size", 0);       if(TYPEOF(Pike_sp[-1]) != T_INT)
pike.git/src/post_modules/Nettle/nettle.cmod:534:    /*! @decl int(0..) key_size()    *! Returns the key size of the encapsulated cipher.    */    PIKEFUN int(0..) key_size()    optflags OPT_EXTERNAL_DEPEND;    {    safe_apply(THIS->object, "key_size", args);    }       /*! @decl this_program set_encrypt_key(string key) -  *! Prepare the cipher and the wrapper for encrypting -  *! with the given @[key]. +  *! +  *! Prepare the cipher and the wrapper for encrypting with the given +  *! @[key]. The @[key] memory will be cleared before released.    */    PIKEFUN object set_encrypt_key(string key)    optflags OPT_SIDE_EFFECT;    {    assert(THIS->block_size);    THIS->mode = 0; -  +  key->flags |= STRING_CLEAR_ON_EXIT;    safe_apply(THIS->object, "set_encrypt_key", args);    pop_stack();    RETURN this_object();    }       /*! @decl this_program set_decrypt_key(string key) -  *! Prepare the cipher and the wrapper for decrypting -  *! with the given @[key]. +  *! +  *! Prepare the cipher and the wrapper for decrypting with the given +  *! @[key]. The @[key] memory will be cleared before released.    */    PIKEFUN object set_decrypt_key(string key)    optflags OPT_SIDE_EFFECT;    {    assert(THIS->block_size);    THIS->mode = 1; -  +  key->flags |= STRING_CLEAR_ON_EXIT;    safe_apply(THIS->object, "set_decrypt_key", args);    pop_stack();    RETURN this_object();    }       /*! @decl this_program set_iv(string iv) -  *! Set the initialization vector to @[iv]. +  *! +  *! Set the initialization vector to @[iv]. The @[iv] memory will be +  *! cleared before released.    */    PIKEFUN object set_iv(string iv)    optflags OPT_SIDE_EFFECT;    {    assert(THIS->iv); -  +  iv->flags |= STRING_CLEAR_ON_EXIT;    NO_WIDE_STRING(iv);    if(iv->len != THIS->block_size)    Pike_error("Argument incompatible with cipher block size.\n");    MEMCPY(THIS->iv, iv->str, THIS->block_size);    RETURN this_object();    }       /*! @decl string(0..255) crypt(string data) -  +  *!    *! Encrypt/decrypt @[data] and return the result. @[data] must    *! be an integral number of blocks. -  +  *! +  *! Neither the input or output data is not automatically memory +  *! scrubbed, unless @[String.secure] has been called on the data.    */    PIKEFUN string(0..255) crypt(string data) {    unsigned INT8 *result;    INT32 offset = 0;    ONERROR uwp; -  struct pike_string * res; +        NO_WIDE_STRING(data);    -  data->flags |= STRING_CLEAR_ON_EXIT; -  +     if(data->len % THIS->block_size)    Pike_error("Data length not multiple of block size.\n");       if(!(result = malloc(data->len)))    SIMPLE_OUT_OF_MEMORY_ERROR("crypt", data->len);    SET_ONERROR (uwp, free, result);       if(THIS->mode == 0) {    while (offset < data->len) {    cbc_encrypt_step((const unsigned INT8 *)data->str + offset,
pike.git/src/post_modules/Nettle/nettle.cmod:612:    }    else {    while (offset < data->len) {    cbc_decrypt_step((const unsigned INT8 *)data->str + offset,    result + offset);    offset += THIS->block_size;    }    }       pop_n_elems(args); -  res = make_shared_binary_string((INT8 *)result, offset); -  res->flags |= STRING_CLEAR_ON_EXIT; -  push_string(res); +  push_string(make_shared_binary_string((INT8 *)result, offset));    guaranteed_memset(result, 0, offset); -  +     CALL_AND_UNSET_ONERROR (uwp);    }   }      /*! @endclass    */      /*! @class Buffer    *! @belongs Crypto    *! Acts as a buffer so that data can be fed to a cipher in blocks
pike.git/src/post_modules/Nettle/nettle.cmod:679:    free(THIS->backlog);    THIS->backlog = NULL;    }    if(THIS->object) {    free_object(THIS->object);    THIS->object = NULL;    }    }       /*! @decl void create(program|object|function cipher, mixed ... args) +  *!    *! Initialize the Proxy wrapper with a cipher algorithm. If it is a -  *! program, an object will be instantiated with @[args] as arguments. -  *! If it is an object that doesn't conform to the cipher API, but has -  *! an @[LFUN::`()], that LFUN will be called. If it is a function, -  *! that function will be called with @[args] as arguments. +  *! program, an object will be instantiated with @[args] as +  *! arguments. If it is an object that doesn't conform to the cipher +  *! API, but has an @[LFUN::`()], that LFUN will be called. If it is +  *! a function, that function will be called with @[args] as +  *! arguments.    */    PIKEFUN void create(program|object|function cipher, mixed ... more)    flags ID_PROTECTED;    {    exit_Proxy_struct();    THIS->object = make_cipher_object(args);       safe_apply(THIS->object, "block_size", 0);    if (TYPEOF(Pike_sp[-1]) != T_INT)    Pike_error("block_size() didn't return an int\n");
pike.git/src/post_modules/Nettle/nettle.cmod:742:    *! Get the key size of the contained block crypto.    */    PIKEFUN int(0..) key_size()    optflags OPT_EXTERNAL_DEPEND;    {    safe_apply(THIS->object, "key_size", args);    }       /*! @decl this_program set_encrypt_key(string key)    *! -  *! Set the encryption key. +  *! Set the encryption key. The @[key] memory will be cleared before +  *! released.    *!    *! @note    *! As a side-effect any buffered data will be cleared.    */    PIKEFUN object set_encrypt_key(string key)    optflags OPT_SIDE_EFFECT;    { -  MEMSET(THIS->backlog, 0, THIS->block_size); +     THIS->backlog_len = 0; -  +  key->flags |= STRING_CLEAR_ON_EXIT;    safe_apply(THIS->object, "set_encrypt_key", args);    pop_stack();    RETURN this_object();    }       /*! @decl this_program set_decrypt_key(string key)    *! -  *! Set the decryption key. +  *! Set the decryption key. The @[key] memory will be cleared before +  *! released.    *!    *! @note    *! As a side-effect any buffered data will be cleared.    */    PIKEFUN object set_decrypt_key(string key)    optflags OPT_SIDE_EFFECT;    { -  MEMSET(THIS->backlog, 0, THIS->block_size); +     THIS->backlog_len = 0; -  +  key->flags |= STRING_CLEAR_ON_EXIT;    safe_apply(THIS->object, "set_decrypt_key", args);    pop_stack();    RETURN this_object();    }       /*! @decl string(0..255) crypt(string data)    *!    *! Encrypt or decrypt some data.    *!    *! Adds data to be en/decrypted to the buffer. If there's enough    *! data to en/decrypt a block, that will be done, and the result    *! returned. Any unprocessed data will be left in the buffer. -  +  *! +  *! Neither the input or output data is not automatically memory +  *! scrubbed, unless @[String.secure] has been called on the data.    */    PIKEFUN string(0..255) crypt(string data) {    unsigned char *result;    ptrdiff_t roffset = 0;    ptrdiff_t soffset = 0;    ptrdiff_t len;    ONERROR uwp; -  struct pike_string * res; +        if (!(result = malloc(data->len + THIS->block_size)))    SIMPLE_OUT_OF_MEMORY_ERROR("crypt", data->len + THIS->block_size);    SET_ONERROR (uwp, free, result);       if (THIS->backlog_len) {    if (data->len >= (THIS->block_size - THIS->backlog_len)) {    MEMCPY(THIS->backlog + THIS->backlog_len, data->str,    (THIS->block_size - THIS->backlog_len));    soffset += (THIS->block_size - THIS->backlog_len);
pike.git/src/post_modules/Nettle/nettle.cmod:812:    safe_apply(THIS->object, "crypt", 1);    if (TYPEOF(Pike_sp[-1]) != T_STRING)    Pike_error("crypt() did not return string\n");    if (Pike_sp[-1].u.string->len != THIS->block_size)    Pike_error("Unexpected string length %ld\n",    DO_NOT_WARN((long)Pike_sp[-1].u.string->len));       MEMCPY(result, Pike_sp[-1].u.string->str, THIS->block_size);    roffset = THIS->block_size;    pop_stack(); -  MEMSET(THIS->backlog, 0, THIS->block_size); +     } else {    MEMCPY(THIS->backlog + THIS->backlog_len,    data->str, data->len);    THIS->backlog_len += data->len;    pop_n_elems(args);    push_empty_string();    CALL_AND_UNSET_ONERROR (uwp);    return;    }    }
pike.git/src/post_modules/Nettle/nettle.cmod:853:    }       if (soffset < Pike_sp[-1].u.string->len) {    MEMCPY(THIS->backlog, Pike_sp[-1].u.string->str + soffset,    Pike_sp[-1].u.string->len - soffset);    THIS->backlog_len = Pike_sp[-1].u.string->len - soffset;    }       pop_n_elems(args);    -  res = make_shared_binary_string((char *)result, roffset + len); -  res->flags |= STRING_CLEAR_ON_EXIT; -  push_string(res); +  push_string(make_shared_binary_string((char *)result, roffset + len));    guaranteed_memset(result, 0, roffset + len);    CALL_AND_UNSET_ONERROR (uwp);    }       /*! @decl string(0..255) pad(void|int method)    *! -  *! Pad and encrypt any data left in the buffer. +  *! Pad and encrypt any data left in the buffer. The output data is +  *! not automatically memory scrubbed, unless @[String.secure] is +  *! called on the data.    *!    *! @param method    *! The type of padding to apply to the buffer.    *! @int    *! @value Crypto.PAD_ISO_10126    *! Pads according to ISO 10126, which means filling all extra    *! space with random data and putting the size of the    *! non-payload data last.    *! @value Crypto.PAD_SSL    *! As ISO 10126, but with the size of the random data last.
pike.git/src/post_modules/Nettle/nettle.cmod:895:    *! @endint    *! Defaults to Crypto.PAD_SSL for compatibility reasons.    *!    *! @seealso    *! @[unpad()]    */    PIKEFUN string(0..255) pad(void|int method) {    ptrdiff_t i;    int m = 0;    int size = THIS->block_size - THIS->backlog_len; -  struct pike_string * backlog; +        if(method)    {    if(TYPEOF(*method) != PIKE_T_INT)    Pike_error("Bad argument type.\n");    m = method->u.integer;    }       switch(m)    {
pike.git/src/post_modules/Nettle/nettle.cmod:943:    THIS->backlog[i] = DO_NOT_WARN((unsigned char)size);    break;    case 4:    /* Null only */    THIS->backlog[i] = 0;    break;    }          THIS->backlog[THIS->block_size - 1] = DO_NOT_WARN((unsigned char)size); -  backlog = make_shared_binary_string((const char *)THIS->backlog, THIS->block_size); -  backlog->flags |= STRING_CLEAR_ON_EXIT; -  push_string(backlog); +  push_string(make_shared_binary_string((const char *)THIS->backlog, THIS->block_size));    -  MEMSET(THIS->backlog, 0, THIS->block_size); +     THIS->backlog_len = 0;       safe_apply(THIS->object, "crypt", 1);    }       /*! @decl string(0..255) unpad(string data, void|int method)    *! -  *! Decrypt and unpad a block of data. +  *! Decrypt and unpad a block of data. Neither the input or output +  *! data is not automatically memory scrubbed, unless +  *! @[String.secure] has been called on the data.    *!    *! This performs the reverse operation of @[pad()].    *!    *! @param method    *! The type of padding that was applied to the original buffer.    *! @int    *! @value Crypto.PAD_SSL    *! @value Crypto.PAD_ISO_10126    *! @value Crypto.PAD_ANSI_X923    *! @value Crypto.PAD_PKCS7    *! @value Crypto.PAD_ZERO    *! @endint    *! Defaults to Crypto.PAD_SSL for compatibility reasons.    *!    *! @seealso    *! @[pad()]    */    PIKEFUN string(0..255) unpad(string str, void|int method) {    ptrdiff_t len;    int m = 0; -  struct pike_string * ret; +        len = str->len + THIS->backlog_len;    if( len % THIS->block_size)    Pike_error("Total data size must be integral numbers of blocks.\n");       if( method!=NULL )    {    m = method->u.integer;    pop_stack();    args--;
pike.git/src/post_modules/Nettle/nettle.cmod:1031:    len--;    }    }    }       if (len < 0)    Pike_error("String too short to unpad\n");       add_ref(str);    pop_stack(); -  ret = make_shared_binary_string(str->str, len); -  ret->flags |= STRING_CLEAR_ON_EXIT; -  push_string(ret); +  push_string(make_shared_binary_string(str->str, len));    free_string(str);    }       /*! @decl this_program set_iv(string iv)    *! Set the initialization vector to @[iv].    */    PIKEFUN object set_iv(string iv)    optflags OPT_SIDE_EFFECT;    {    apply(THIS->object, "set_iv", args);