56c0642008-07-31Martin Stjernholm /* -*- c -*- || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
c735c02003-03-18Niels Möller 
b63de32018-01-19Martin Nilsson #include "module.h"
c735c02003-03-18Niels Möller #include "interpret.h"
8048062003-12-06Martin Nilsson #include "operators.h"
602fe62004-02-21Martin Nilsson #include "threads.h"
f36a622017-02-09Henrik Grubbström (Grubba) #include "pike_compiler.h"
c735c02003-03-18Niels Möller #include "module_support.h" #include "nettle_config.h" #ifdef HAVE_LIBNETTLE
56c0642008-07-31Martin Stjernholm DECLARATIONS
c735c02003-03-18Niels Möller #include "nettle.h"
9b69512014-05-01Henrik Grubbström (Grubba) #include <nettle/memxor.h>
c735c02003-03-18Niels Möller #include <nettle/aes.h>
07e4b62013-10-28Henrik Grubbström (Grubba) #include <nettle/arctwo.h>
8417e52003-08-24Martin Nilsson #include <nettle/arcfour.h>
85fc8e2011-04-21Martin Nilsson #ifdef HAVE_NETTLE_BLOWFISH_DECRYPT
1b34712003-08-25Martin Nilsson #include <nettle/blowfish.h>
dc4a972008-07-17Martin Stjernholm #endif
650f102011-12-23Henrik Grubbström (Grubba) #ifdef HAVE_NETTLE_CAMELLIA_H #include <nettle/camellia.h> #endif
408f682003-07-29Martin Nilsson #include <nettle/cast128.h>
24b0bd2014-04-18Henrik Grubbström (Grubba) #ifdef HAVE_NETTLE_CHACHA_H #include <nettle/chacha.h> #endif
f3b8d42013-11-12Martin Nilsson #include <nettle/des.h> #ifdef HAVE_NETTLE_SALSA20_CRYPT #include <nettle/salsa20.h> #endif
85fc8e2011-04-21Martin Nilsson #ifdef HAVE_NETTLE_SERPENT_DECRYPT
408f682003-07-29Martin Nilsson #include <nettle/serpent.h>
dc4a972008-07-17Martin Stjernholm #endif
408f682003-07-29Martin Nilsson #include <nettle/twofish.h>
fc06892003-11-27Martin Nilsson #include "idea.h"
c735c02003-03-18Niels Möller 
efd5ff2013-11-30Henrik Grubbström (Grubba) #include <nettle/cbc.h>
f8b7242015-04-17Martin Nilsson #include <nettle/ctr.h>
efd5ff2013-11-30Henrik Grubbström (Grubba) 
3add1f2003-03-25Martin Nilsson /*! @module Nettle */
c735c02003-03-18Niels Möller 
9b69512014-05-01Henrik Grubbström (Grubba) static struct pike_string *nul13_string = NULL; static struct pike_string *nul16_string = NULL;
ef84602014-04-26Henrik Grubbström (Grubba) /* Generic callback function for Nettle in case the crypt() * function in the object isn't a Nettle function. */
6ef3c12014-11-06Henrik Grubbström (Grubba) #ifdef dsa_params_init /* Nettle 3.0 */
64337a2014-11-06Martin Nilsson static void pike_crypt_func(const void *object, pike_nettle_size_t length,
ef84602014-04-26Henrik Grubbström (Grubba)  uint8_t *dst, const uint8_t *src)
6ef3c12014-11-06Henrik Grubbström (Grubba) #else static void pike_crypt_func(void *object, pike_nettle_size_t length, uint8_t *dst, const uint8_t *src) #endif
ef84602014-04-26Henrik Grubbström (Grubba) { struct pike_string *str; push_string(make_shared_binary_string((const char *)src, length));
6424ff2014-11-06Martin Nilsson  apply((struct object *)object, "crypt", 1);
391ac52018-08-05Martin Nilsson  get_all_args(NULL, 1, "%n", &str);
ef84602014-04-26Henrik Grubbström (Grubba)  if (str->len != (ptrdiff_t)length) { Pike_error("Bad string length %ld returned from crypt()\n",
77af4f2015-10-14Martin Nilsson  (long)str->len);
ef84602014-04-26Henrik Grubbström (Grubba)  }
59fc9e2014-09-03Martin Nilsson  memcpy(dst, str->str, length);
8c53732014-05-13Henrik Grubbström (Grubba)  pop_stack();
ef84602014-04-26Henrik Grubbström (Grubba) }
c4316a2015-04-15Henrik Grubbström (Grubba) #if !defined(HAVE_MEMXOR3) && !defined(memxor3) /* Really old versions of nettle don't have memxor3(). * * Note that prior to Nettle 3.1 memxor3() didn't have a namespace prefix. */
ceff142015-03-18Henrik Grubbström (Grubba) static unsigned char *pike_memxor3(unsigned char *dst, const unsigned char *a, const unsigned char *b, size_t n) { size_t i; for(i = 0; i < n; i++) { dst[i] = a[i]^b[i]; } return dst; } #define memxor3(D, A, B, N) pike_memxor3((D), (A), (B), (N)) #endif
4db33a2015-12-18Henrik Grubbström (Grubba) /* Rotate src left and xor to destination. */
85813a2015-12-19Henrik Grubbström (Grubba) static unsigned char *pike_memrolx(unsigned char *dst, const unsigned char *src,
4db33a2015-12-18Henrik Grubbström (Grubba)  size_t shift, size_t n) {
50ec542015-12-20Henrik Grubbström (Grubba)  /* FIXME: Could be possibly optimized by reading larger quantities on
4db33a2015-12-18Henrik Grubbström (Grubba)  * big-endian architectures. */
50ec542015-12-20Henrik Grubbström (Grubba)  size_t i, k;
85813a2015-12-19Henrik Grubbström (Grubba)  if (!n) return dst;
50ec542015-12-20Henrik Grubbström (Grubba)  /* Calculate the number of full bytes to rotate. */ k = (shift >> 3); if (k > n) { k %= n; } k = n - k; shift = shift & 0x07; if (!shift) { size_t i = n; if (!k || (k == n)) { /* Noop rotation. */ return memxor(dst, src, n); } while (i--) { if (!(k--)) k = n - 1; dst[k] ^= src[i]; } } else { unsigned char prev_overflow = src[0]>>(8 - shift); size_t i = n; while (i--) { unsigned char next_overflow = src[i]>>(8 - shift);
aed7b52015-12-20Martin Nilsson  if (!(k--)) k = n - 1;
50ec542015-12-20Henrik Grubbström (Grubba)  dst[k] ^= (src[i]<<shift) | prev_overflow; prev_overflow = next_overflow; }
4db33a2015-12-18Henrik Grubbström (Grubba)  } return dst; }
85813a2015-12-19Henrik Grubbström (Grubba) #define memrolx(D, S, L, N) pike_memrolx((D), (S), (L), (N))
4db33a2015-12-18Henrik Grubbström (Grubba) 
13670c2015-05-25Martin Nilsson /* Calls Pike_error on errors */
662c982003-11-09Niels Möller typedef void (*pike_nettle_set_key_func)(void *ctx, ptrdiff_t length, const char *key, /* Force means to use key even if it is weak */ int force);
c735c02003-03-18Niels Möller 
662c982003-11-09Niels Möller struct pike_cipher { const char *name;
13670c2015-05-25Martin Nilsson 
662c982003-11-09Niels Möller  unsigned context_size;
fc06892003-11-27Martin Nilsson 
662c982003-11-09Niels Möller  unsigned block_size; /* Suggested key size; other sizes are sometimes possible. */ unsigned key_size; pike_nettle_set_key_func set_encrypt_key; pike_nettle_set_key_func set_decrypt_key;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func encrypt; pike_nettle_crypt_func decrypt;
662c982003-11-09Niels Möller }; #define _PIKE_CIPHER(name, NAME) { \ #name, \ sizeof(struct name##_ctx), \ NAME##_BLOCK_SIZE, \ NAME##_KEY_SIZE, \ pike_##name##_set_encrypt_key, \ pike_##name##_set_decrypt_key, \
fd073e2014-06-23Henrik Grubbström (Grubba)  (pike_nettle_crypt_func) name##_encrypt, \ (pike_nettle_crypt_func) name##_decrypt, \
662c982003-11-09Niels Möller }
c1f5ab2003-08-26Martin Nilsson 
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define STREAM_MODE "stream" #cmod_define BLOCK_MODE "block" #cmod_define BLOCK16_MODE "block16"
4d65952013-10-21Henrik Grubbström (Grubba) /*! @class Cipher
c735c02003-03-18Niels Möller  *! *! Represents information about a cipher algorithm, such as *! name, key size, and block size. */
4d65952013-10-21Henrik Grubbström (Grubba) PIKECLASS Cipher
c735c02003-03-18Niels Möller {
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @decl inherit __builtin.Nettle.Cipher */ INHERIT "__builtin.Nettle.Cipher";
662c982003-11-09Niels Möller  CVAR const struct pike_cipher *meta;
3747282014-04-30Henrik Grubbström (Grubba)  DECLARE_STORAGE;
13670c2015-05-25Martin Nilsson 
b467522017-06-25Martin Nilsson #ifdef PIKE_NULL_IS_SPECIAL
3747282014-04-30Henrik Grubbström (Grubba)  INIT { THIS->meta = NULL; }
b467522017-06-25Martin Nilsson #endif
3747282014-04-30Henrik Grubbström (Grubba) 
f6a6ad2013-12-08Henrik Grubbström (Grubba)  /*! @decl string(0..255) name()
c735c02003-03-18Niels Möller  *!
127b2f2003-03-18Niels Möller  *! @returns *! A human readable name for the algorithm.
c735c02003-03-18Niels Möller  */
5345c92013-05-19Martin Nilsson  PIKEFUN string(0..255) name()
1a2b712004-02-14Martin Nilsson  optflags OPT_TRY_OPTIMIZE;
4d65952013-10-21Henrik Grubbström (Grubba)  { if (!THIS->meta) Pike_error("Cipher not properly initialized.\n");
c735c02003-03-18Niels Möller 
4d65952013-10-21Henrik Grubbström (Grubba)  push_text(THIS->meta->name); }
c735c02003-03-18Niels Möller 
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) key_size()
c735c02003-03-18Niels Möller  *!
127b2f2003-03-18Niels Möller  *! @returns *! The recommended key size for the cipher.
c735c02003-03-18Niels Möller  */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) key_size()
1a2b712004-02-14Martin Nilsson  optflags OPT_TRY_OPTIMIZE;
4d65952013-10-21Henrik Grubbström (Grubba)  { if (!THIS->meta) Pike_error("Cipher not properly initialized.\n");
c735c02003-03-18Niels Möller 
4d65952013-10-21Henrik Grubbström (Grubba)  push_int(THIS->meta->key_size); }
13670c2015-05-25Martin Nilsson 
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) block_size()
c735c02003-03-18Niels Möller  *!
127b2f2003-03-18Niels Möller  *! @returns
01a1ba2003-12-14Martin Nilsson  *! The block size of the cipher (1 for stream ciphers).
c735c02003-03-18Niels Möller  */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) block_size()
1a2b712004-02-14Martin Nilsson  optflags OPT_TRY_OPTIMIZE;
4d65952013-10-21Henrik Grubbström (Grubba)  { if (!THIS->meta) Pike_error("Cipher not properly initialized.\n"); push_int(THIS->meta->block_size); }
c735c02003-03-18Niels Möller 
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @class State *! *! Base class for cipher contexts. */ PIKECLASS State
9e336b2014-06-19Henrik Grubbström (Grubba)  program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;
4d65952013-10-21Henrik Grubbström (Grubba)  { DOCSTART() @decl inherit Cipher::State DOCEND() EXTRA
c735c02003-03-18Niels Möller  {
4d65952013-10-21Henrik Grubbström (Grubba)  /* Perform an inherit of the State class (if any) that our parent * may contain via its inherit of __builtin.Nettle.Hash. */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
c735c02003-03-18Niels Möller  }
fd073e2014-06-23Henrik Grubbström (Grubba)  CVAR pike_nettle_crypt_func crypt;
4d65952013-10-21Henrik Grubbström (Grubba)  CVAR void *ctx; CVAR int key_size;
c735c02003-03-18Niels Möller 
4d65952013-10-21Henrik Grubbström (Grubba)  /* FIXME: Create should copy state from the other object, if * provided. */
d55fde2003-11-28Martin Nilsson 
13e2ba2014-04-26Henrik Grubbström (Grubba) #define GET_INFO() ((struct Nettle_Cipher_struct *)parent_storage(1, Nettle_Cipher_program))
1b34712003-08-25Martin Nilsson 
83fe4f2014-04-30Henrik Grubbström (Grubba)  /*! @decl State set_encrypt_key(string(0..255) key, void|int flags)
4d65952013-10-21Henrik Grubbström (Grubba)  *! *! Initializes the object for encryption. The @[key] memory will be *! cleared before released. *! *! @seealso *! @[set_decrypt_key], @[crypt] */
83fe4f2014-04-30Henrik Grubbström (Grubba)  PIKEFUN object set_encrypt_key(string(0..255) key, void|int flags)
4d65952013-10-21Henrik Grubbström (Grubba)  optflags OPT_SIDE_EFFECT;
895c722014-03-29Henrik Grubbström (Grubba)  rawtype tFunc(tStr8 tOr(tInt, tVoid), tObjImpl_NETTLE_CIPHER_STATE);
c735c02003-03-18Niels Möller  {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *info = GET_INFO();
c735c02003-03-18Niels Möller  assert(info);
4d65952013-10-21Henrik Grubbström (Grubba) 
c735c02003-03-18Niels Möller  if (!THIS->ctx || !info->meta)
f1c9f42003-08-05Martin Nilsson  Pike_error("CipherState not properly initialized.\n");
c735c02003-03-18Niels Möller  NO_WIDE_STRING(key);
bb64932013-08-09Arne Goedeke  key->flags |= STRING_CLEAR_ON_EXIT;
662c982003-11-09Niels Möller  info->meta->set_encrypt_key(THIS->ctx, key->len, key->str,
83fe4f2014-04-30Henrik Grubbström (Grubba)  flags ? flags->u.integer : 0);
c1f5ab2003-08-26Martin Nilsson 
c735c02003-03-18Niels Möller  THIS->crypt = info->meta->encrypt;
1b34712003-08-25Martin Nilsson  THIS->key_size = key->len;
c735c02003-03-18Niels Möller 
2e0ac22014-03-20Henrik Grubbström (Grubba)  RETURN this_object();
c735c02003-03-18Niels Möller  }
83fe4f2014-04-30Henrik Grubbström (Grubba)  /*! @decl State set_decrypt_key(string(0..255) key, void|int flags)
4d65952013-10-21Henrik Grubbström (Grubba)  *! *! Initializes the object for decryption. The @[key] memory will be *! cleared before released. *! *! @seealso *! @[set_encrypt_key], @[crypt] */
83fe4f2014-04-30Henrik Grubbström (Grubba)  PIKEFUN object set_decrypt_key(string(0..255) key, void|int flags)
4d65952013-10-21Henrik Grubbström (Grubba)  optflags OPT_SIDE_EFFECT;
895c722014-03-29Henrik Grubbström (Grubba)  rawtype tFunc(tStr8 tOr(tInt, tVoid), tObjImpl_NETTLE_CIPHER_STATE);
c735c02003-03-18Niels Möller  {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *info = GET_INFO();
c735c02003-03-18Niels Möller  assert(info);
13670c2015-05-25Martin Nilsson 
c735c02003-03-18Niels Möller  if (!THIS->ctx || !info->meta)
f1c9f42003-08-05Martin Nilsson  Pike_error("CipherState not properly initialized.\n");
c735c02003-03-18Niels Möller  NO_WIDE_STRING(key);
bb64932013-08-09Arne Goedeke  key->flags |= STRING_CLEAR_ON_EXIT;
662c982003-11-09Niels Möller  info->meta->set_decrypt_key(THIS->ctx, key->len, key->str,
83fe4f2014-04-30Henrik Grubbström (Grubba)  flags ? flags->u.integer : 0);
c735c02003-03-18Niels Möller  THIS->crypt = info->meta->decrypt;
1b34712003-08-25Martin Nilsson  THIS->key_size = key->len;
c735c02003-03-18Niels Möller 
2e0ac22014-03-20Henrik Grubbström (Grubba)  RETURN this_object();
c735c02003-03-18Niels Möller  }
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @decl string(0..255) make_key() *!
30fc482016-03-14Martin Nilsson  *! Generate a key by calling @[random_string] and initialize this *! object for encryption with that key.
4d65952013-10-21Henrik Grubbström (Grubba)  *! *! @returns *! The generated key. The key memory will be cleared before
076f4f2017-08-18Henrik Grubbström (Grubba)  *! being released.
4d65952013-10-21Henrik Grubbström (Grubba)  *! *! @seealso *! @[set_encrypt_key] */
5345c92013-05-19Martin Nilsson  PIKEFUN string(0..255) make_key()
4d65952013-10-21Henrik Grubbström (Grubba)  optflags OPT_EXTERNAL_DEPEND; {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *info = GET_INFO();
4d65952013-10-21Henrik Grubbström (Grubba)  assert(info);
d55fde2003-11-28Martin Nilsson 
076f4f2017-08-18Henrik Grubbström (Grubba)  /* NB: Some ciphers (eg Blowfish) have weak keys, for which * set_encrypt_key() will throw an error. We thus need * to retry with a new key on error. */ while(1) { JMP_BUF recover; if (!SETJMP(recover)) { push_random_string(info->meta->key_size); stack_dup(); Pike_sp[-1].u.string->flags |= STRING_CLEAR_ON_EXIT; apply_current(f_Nettle_Cipher_State_set_encrypt_key_fun_num, 1); pop_stack(); UNSETJMP(recover); return; } UNSETJMP(recover); }
4d65952013-10-21Henrik Grubbström (Grubba)  }
d55fde2003-11-28Martin Nilsson 
f6a6ad2013-12-08Henrik Grubbström (Grubba)  /*! @decl string(0..255) crypt(string(0..255) data)
4d65952013-10-21Henrik Grubbström (Grubba)  *! *! Encrypts or decrypts data, using the current key. Neither the *! input nor output data is automatically memory scrubbed, *! unless @[String.secure] has been called on them. *! *! @param data *! For block ciphers, data must be an integral number of blocks. *! *! @returns *! The encrypted or decrypted data. */
f6a6ad2013-12-08Henrik Grubbström (Grubba)  PIKEFUN string(0..255) crypt (string(0..255) data)
4d65952013-10-21Henrik Grubbström (Grubba)  optflags OPT_EXTERNAL_DEPEND | OPT_SIDE_EFFECT;
c735c02003-03-18Niels Möller  {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *info = GET_INFO();
c735c02003-03-18Niels Möller  struct pike_string *s;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func crypt;
0473d52014-05-11Henrik Grubbström (Grubba)  void *ctx;
c735c02003-03-18Niels Möller  assert(info);
4d65952013-10-21Henrik Grubbström (Grubba) 
0473d52014-05-11Henrik Grubbström (Grubba)  if (!(ctx = THIS->ctx) || !(crypt = THIS->crypt) || !info->meta)
f1c9f42003-08-05Martin Nilsson  Pike_error("CipherState not properly initialized.\n");
c735c02003-03-18Niels Möller  NO_WIDE_STRING(data);
5040d82003-11-29Martin Nilsson  if (data->len % info->meta->block_size)
f1c9f42003-08-05Martin Nilsson  Pike_error("Data must be an integral number of blocks.\n");
c735c02003-03-18Niels Möller  s = begin_shared_string(data->len);
0473d52014-05-11Henrik Grubbström (Grubba)  if (data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) { THREADS_ALLOW(); crypt(ctx, data->len, STR0(s), STR0(data)); THREADS_DISALLOW(); } else { crypt(ctx, data->len, STR0(s), STR0(data)); }
bb64932013-08-09Arne Goedeke  s = end_shared_string(s); push_string(s);
c735c02003-03-18Niels Möller  }
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @decl string(0..255) name(void) *! *! @returns *! A human readable name for the algorithm. *! *! @note *! The default implementation just calls @[Cipher::name()] *! in the parent. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
895c722014-03-29Henrik Grubbström (Grubba)  apply_external(1, f_Nettle_Cipher_name_fun_num, args);
4d65952013-10-21Henrik Grubbström (Grubba)  }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) key_size(void)
4d65952013-10-21Henrik Grubbström (Grubba)  *! *! @returns *! The actual key size for this cipher. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) key_size()
4d65952013-10-21Henrik Grubbström (Grubba)  optflags OPT_TRY_OPTIMIZE;
1b34712003-08-25Martin Nilsson  { RETURN THIS->key_size; }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) block_size(void)
4d65952013-10-21Henrik Grubbström (Grubba)  *! *! @returns *! The block size for this cipher. *! *! @note *! The default implementation just calls @[Cipher::block_size()] *! in the parent. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) block_size()
4d65952013-10-21Henrik Grubbström (Grubba)  optflags OPT_TRY_OPTIMIZE; {
895c722014-03-29Henrik Grubbström (Grubba)  apply_external(1, f_Nettle_Cipher_block_size_fun_num, args);
4d65952013-10-21Henrik Grubbström (Grubba)  }
b467522017-06-25Martin Nilsson #ifdef PIKE_NULL_IS_SPECIAL
4d65952013-10-21Henrik Grubbström (Grubba)  INIT
c735c02003-03-18Niels Möller  { THIS->ctx = NULL; THIS->crypt = NULL;
68108c2003-08-26Martin Nilsson  THIS->key_size = 0;
c735c02003-03-18Niels Möller  }
b467522017-06-25Martin Nilsson #endif
c735c02003-03-18Niels Möller 
4d65952013-10-21Henrik Grubbström (Grubba)  EXIT
c735c02003-03-18Niels Möller  {
2d5a562003-05-08Henrik Grubbström (Grubba)  if (THIS->ctx && Pike_fp->current_object->prog)
c735c02003-03-18Niels Möller  {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *info = GET_INFO();
c735c02003-03-18Niels Möller  assert(info); assert(info->meta); memset(THIS->ctx, 0, info->meta->context_size); } }
4d65952013-10-21Henrik Grubbström (Grubba)  }
3747282014-04-30Henrik Grubbström (Grubba)  /*! @endclass State */
c735c02003-03-18Niels Möller }
ef84602014-04-26Henrik Grubbström (Grubba) 
4d65952013-10-21Henrik Grubbström (Grubba) /*! @endclass Cipher */
c735c02003-03-18Niels Möller 
83fe4f2014-04-30Henrik Grubbström (Grubba) /*! @class BufferedCipher *! *! Extends the @[Cipher] class with the @[Buffer] *! meta cipher. This is in turn inherited by the *! @[BlockCipher] class, which is the base class *! for all block ciphers. */ PIKECLASS BufferedCipher { /* NOTE: MUST be first in the class to simplify access to symbols * in Cipher! */ /*! @decl inherit Cipher */
2194f92018-11-04Marcus Comstedt  INHERIT Cipher;
83fe4f2014-04-30Henrik Grubbström (Grubba)  #define PAD_SSL 0 #define PAD_ISO_10126 1 #define PAD_ANSI_X923 2 #define PAD_PKCS7 3 #define PAD_ZERO 4 #define PAD_TLS 5 /*! @module Buffer *! Acts as a buffer so that data can be fed to the cipher in blocks *! that don't correspond to cipher block sizes. *! *! @example *! class Encrypter *! { *! protected Crypto.Cipher buffer; *! *! void create(string key) *! {
a797162014-04-30Henrik Grubbström (Grubba)  *! buffer = Crypto.AES.CBC.Buffer();
83fe4f2014-04-30Henrik Grubbström (Grubba)  *! buffer->set_encrypt_key(key); *! } *! *! string feed(string data) *! { *! return buffer->crypt(data); *! } *! *! string drain() *! { *! return buffer->pad(Crypto.PAD_PKCS7); *! } *! } *! *! @seealso *! @[BlockCipher.CBC], @[BlockCipher16.GCM] */ PIKEVAR object(Nettle_BufferedCipher_cq__Buffer) Buffer; PIKECLASS _Buffer program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit __builtin.Nettle.Cipher */ INHERIT "__builtin.Nettle.Cipher";
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; { apply_external(1, f_Nettle_Cipher_name_fun_num, args); push_constant_text(".Buffer"); f_add(2); } PIKEFUN int(1..) block_size() { apply_external(1, f_Nettle_Cipher_block_size_fun_num, args); } PIKEFUN int(1..) key_size() { apply_external(1, f_Nettle_Cipher_key_size_fun_num, args); } PIKEFUN int(0..) iv_size() { apply_external(1, f_Nettle_Cipher_block_size_fun_num, args); }
83fe4f2014-04-30Henrik Grubbström (Grubba) 
a797162014-04-30Henrik Grubbström (Grubba)  /*! @class State *! Acts as a buffer so that data can be fed to the cipher in blocks *! that don't correspond to cipher block sizes. *! *! @example *! class Encrypter *! { *! protected Crypto.Cipher buffer; *! *! void create(string key) *! { *! buffer = Crypto.AES.CBC.Buffer(); *! buffer->set_encrypt_key(key); *! } *! *! string feed(string data) *! { *! return buffer->crypt(data); *! } *! *! string drain() *! { *! return buffer->pad(Crypto.PAD_PKCS7); *! } *! } *! *! @seealso *! @[BlockCipher.CBC], @[BlockCipher16.GCM] */
83fe4f2014-04-30Henrik Grubbström (Grubba)  PIKECLASS State
9e336b2014-06-19Henrik Grubbström (Grubba)  program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT|PROGRAM_CLEAR_STORAGE;
83fe4f2014-04-30Henrik Grubbström (Grubba)  { CVAR struct object *object; CVAR int block_size; CVAR unsigned char *backlog; CVAR int backlog_len;
b467522017-06-25Martin Nilsson #ifdef PIKE_NULL_IS_SPECIAL
83fe4f2014-04-30Henrik Grubbström (Grubba)  INIT { THIS->object = NULL; THIS->block_size = 0; THIS->backlog = NULL; THIS->backlog_len = 0; }
b467522017-06-25Martin Nilsson #endif
83fe4f2014-04-30Henrik Grubbström (Grubba)  EXIT gc_trivial; { if(THIS->backlog) {
34a7972018-01-18Martin Nilsson  secure_zero(THIS->backlog, THIS->block_size);
83fe4f2014-04-30Henrik Grubbström (Grubba)  free(THIS->backlog);
40338f2017-07-10Martin Nilsson  } if(THIS->object)
fc8db32017-07-11Martin Nilsson  { free_object(THIS->object); THIS->object = NULL; }
83fe4f2014-04-30Henrik Grubbström (Grubba)  }
2680122014-05-02Henrik Grubbström (Grubba)  /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on.
83fe4f2014-04-30Henrik Grubbström (Grubba)  *!
2680122014-05-02Henrik Grubbström (Grubba)  *! Defaults to creating the State for the cipher implemented
83fe4f2014-04-30Henrik Grubbström (Grubba)  *! in the parent module. */
2680122014-05-02Henrik Grubbström (Grubba)  PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; { apply_external(2, Nettle_Cipher_State_program_fun_num, 0); } /*! @decl void create() *! *! Initialize the buffer with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module. */
83fe4f2014-04-30Henrik Grubbström (Grubba)  PIKEFUN void create() flags ID_PROTECTED; { struct object *o; int block_size; int f; exit_Nettle_BufferedCipher_cq__Buffer_State_struct();
2680122014-05-02Henrik Grubbström (Grubba)  apply_current(f_Nettle_BufferedCipher_cq__Buffer_State_substate_factory_fun_num, 0);
83fe4f2014-04-30Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); }
8c53732014-05-13Henrik Grubbström (Grubba)  apply(o, "block_size", 0);
83fe4f2014-04-30Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if ((!block_size) || (block_size > 4096)) Pike_error("Bad block size %d.\n", block_size); THIS->block_size = block_size; THIS->backlog = xcalloc(1, block_size); THIS->backlog_len = 0;
65810c2017-12-28Martin Nilsson  add_ref(THIS->object = o); pop_n_elems(2);
83fe4f2014-04-30Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the name of the wrapped cipher with @expr{".Buffer"@} *! appended. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "name", 0);
83fe4f2014-04-30Henrik Grubbström (Grubba)  push_constant_text(".Buffer"); f_add(2); }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) block_size()
83fe4f2014-04-30Henrik Grubbström (Grubba)  *! *! Get the block size of the contained block crypto. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) block_size()
83fe4f2014-04-30Henrik Grubbström (Grubba)  optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) key_size()
83fe4f2014-04-30Henrik Grubbström (Grubba)  *! *! Get the key size of the contained block crypto. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) key_size()
83fe4f2014-04-30Henrik Grubbström (Grubba)  optflags OPT_EXTERNAL_DEPEND; {
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "key_size", args); } /*! @decl int(0..) iv_size() *! *! Get the iv size of the contained block crypto. */ PIKEFUN int(0..) iv_size() optflags OPT_EXTERNAL_DEPEND; { apply(THIS->object, "iv_size", args);
83fe4f2014-04-30Henrik Grubbström (Grubba)  } /*! @decl this_program set_encrypt_key(string(0..255) key, @ *! void|int flags) *! *! 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(0..255) key, void|int flags) optflags OPT_SIDE_EFFECT; { THIS->backlog_len = 0; key->flags |= STRING_CLEAR_ON_EXIT;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_encrypt_key", args);
83fe4f2014-04-30Henrik Grubbström (Grubba)  pop_stack(); push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, @ *! void|int flags) *! *! 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(0..255) key, void|int flags) optflags OPT_SIDE_EFFECT; { THIS->backlog_len = 0; key->flags |= STRING_CLEAR_ON_EXIT;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_decrypt_key", args);
83fe4f2014-04-30Henrik Grubbström (Grubba)  pop_stack(); push_object(this_object()); } /*! @decl string(0..255) crypt(string(0..255) 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(0..255) data) { ptrdiff_t strings = 0; ptrdiff_t soffset = 0; ptrdiff_t len; if (THIS->backlog_len) { if (data->len >= (THIS->block_size - THIS->backlog_len)) {
59fc9e2014-09-03Martin Nilsson  memcpy(THIS->backlog + THIS->backlog_len, data->str,
83fe4f2014-04-30Henrik Grubbström (Grubba)  (THIS->block_size - THIS->backlog_len)); soffset += (THIS->block_size - THIS->backlog_len); THIS->backlog_len = 0; push_string(make_shared_binary_string((char *)THIS->backlog, THIS->block_size));
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "crypt", 1);
83fe4f2014-04-30Henrik Grubbström (Grubba)  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",
77af4f2015-10-14Martin Nilsson  (long)Pike_sp[-1].u.string->len);
83fe4f2014-04-30Henrik Grubbström (Grubba)  strings++; } else {
59fc9e2014-09-03Martin Nilsson  memcpy(THIS->backlog + THIS->backlog_len,
83fe4f2014-04-30Henrik Grubbström (Grubba)  data->str, data->len); THIS->backlog_len += data->len; pop_n_elems(args); push_empty_string(); return; } } len = (data->len - soffset); len -= len % THIS->block_size; if (len) { push_string( string_slice( data, soffset, len ) ); soffset += len;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "crypt", 1);
83fe4f2014-04-30Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) != T_STRING) Pike_error("crypt() did not return string.\n"); if (Pike_sp[-1].u.string->len != len) Pike_error("crypt() Unexpected string length %ld.\n",
77af4f2015-10-14Martin Nilsson  (long)Pike_sp[-1].u.string->len);
83fe4f2014-04-30Henrik Grubbström (Grubba)  strings++; } if (soffset < data->len) {
59fc9e2014-09-03Martin Nilsson  memcpy(THIS->backlog, data->str + soffset, data->len - soffset);
83fe4f2014-04-30Henrik Grubbström (Grubba)  THIS->backlog_len = data->len - soffset; } if( !strings ) push_empty_string(); else if( strings > 1 ) f_add( strings ); stack_pop_n_elems_keep_top(args); } /*! @decl string(0..255) pad(void|int method) *! *! 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_TLS *! @value Crypto.PAD_SSL
0c4ea52015-08-22Martin Nilsson  *! Pads according to @rfc{5246:6.2.3.2@}, meaning that all *! extra space is filled with the size of the padding. Note *! that this size has an off by one difference to the other *! schemas, so 0 means 1 byte of padding.
83fe4f2014-04-30Henrik Grubbström (Grubba)  *! @value Crypto.PAD_ANSI_X923 *! Pads according to ANSI X.923, which means filling all extra *! space with zero and putting the size of the non-payload data *! last. *! @value Crypto.PAD_PKCS7
974d4a2015-08-22Martin Nilsson  *! Pads according to PKCS7 / @rfc{3852@}, which means *! filling all extra space with the size of the extra *! space.
83fe4f2014-04-30Henrik Grubbström (Grubba)  *! @value Crypto.PAD_ZERO *! Fills the extra space with null bytes. To correctly remove *! the padding the clear text data must not end with a null *! byte. In that case the data would have to be manually *! padded/unpadded before/after calling @[crypt()]. *! @endint *! Defaults to Crypto.PAD_SSL for compatibility reasons. *! *! @seealso *! @[unpad()] */ PIKEFUN string(0..255) pad(void|int method) { ptrdiff_t i;
3aba5c2016-03-12Martin Nilsson  int m = PAD_SSL;
83fe4f2014-04-30Henrik Grubbström (Grubba)  int size = THIS->block_size - THIS->backlog_len; if(method) { if(TYPEOF(*method) != PIKE_T_INT) Pike_error("Bad argument type.\n"); m = method->u.integer;
3aba5c2016-03-12Martin Nilsson  }
83fe4f2014-04-30Henrik Grubbström (Grubba)  switch(m) { case PAD_SSL: case PAD_TLS: size--; break; case PAD_ZERO: if( THIS->backlog_len>0 && THIS->backlog[THIS->backlog_len-1] == 0 ) Pike_error("Using zero padding on a zero terminated string.\n"); size = 0; break; }
3aba5c2016-03-12Martin Nilsson  if( m == PAD_ISO_10126 ) { push_random_string(THIS->block_size-THIS->backlog_len); }
83fe4f2014-04-30Henrik Grubbström (Grubba)  for (i = THIS->backlog_len; i < THIS->block_size - 1; i++) switch(m) { default: Pike_error("Unknown method.\n"); case PAD_SSL: case PAD_TLS: /* TLS 1.1 and forward */ THIS->backlog[i] = size; break; case PAD_ISO_10126: /* ISO 10126 */
3aba5c2016-03-12Martin Nilsson  THIS->backlog[i] = (unsigned char)Pike_sp[-1].u.string->str[i-THIS->backlog_len];
83fe4f2014-04-30Henrik Grubbström (Grubba)  break; case PAD_ANSI_X923: /* ANSI X.923 */ THIS->backlog[i] = 0; break; case PAD_PKCS7: /* PKCS7 / RFC 3852 */
77af4f2015-10-14Martin Nilsson  THIS->backlog[i] = (unsigned char)size;
83fe4f2014-04-30Henrik Grubbström (Grubba)  break; case PAD_ZERO: /* Null only */ THIS->backlog[i] = 0; break; }
77af4f2015-10-14Martin Nilsson  THIS->backlog[THIS->block_size - 1] = (unsigned char)size;
83fe4f2014-04-30Henrik Grubbström (Grubba)  push_string(make_shared_binary_string((const char *)THIS->backlog, THIS->block_size)); THIS->backlog_len = 0;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "crypt", 1);
83fe4f2014-04-30Henrik Grubbström (Grubba)  } /*! @decl string(0..255) unpad(string(0..255) data, void|int method) *! *! 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()]. The padding *! will be verified to be correct, if possible. If not, zero is *! returned. *! *! @param method *! The type of padding that was applied to the original buffer. *! @int *! @value Crypto.PAD_SSL *! @value Crypto.PAD_TLS *! @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(0..255) str, void|int method) { ptrdiff_t len, bytes; int m = 0, i, invalid = 0, padding=0; 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--; } f_Nettle_BufferedCipher_cq__Buffer_State_crypt(1); if (TYPEOF(Pike_sp[-1]) != T_STRING) Pike_error("crypt() did not return string.\n"); if (Pike_sp[-1].u.string->len != len) Pike_error("crypt() Unexpected string length %ld.\n",
77af4f2015-10-14Martin Nilsson  (long)Pike_sp[-1].u.string->len);
83fe4f2014-04-30Henrik Grubbström (Grubba)  str = Pike_sp[-1].u.string;
8b2ebd2014-07-21Henrik Grubbström (Grubba)  bytes = STR0(str)[len - 1];
83fe4f2014-04-30Henrik Grubbström (Grubba)  if( m==PAD_SSL || m==PAD_TLS ) bytes++; /* FIXME: Shouldn't this be supported? */
8b2ebd2014-07-21Henrik Grubbström (Grubba)  if (bytes > str->len) Pike_error("Invalid padding (%d > %d)\n", bytes, str->len);
83fe4f2014-04-30Henrik Grubbström (Grubba)  switch( m ) { default: Pike_error("Unknown method.\n"); case PAD_ISO_10126: case PAD_ZERO: case PAD_SSL: break; case PAD_ANSI_X923: padding = 0; goto do_check; case PAD_TLS: padding = bytes-1; goto do_check; case PAD_PKCS7: padding = bytes; do_check: /* Try to be constant time here. */
8b2ebd2014-07-21Henrik Grubbström (Grubba)  invalid = 1; for(i=len-256; i<len-1; i++) { if (i < 0) i = 0; if (i == len-bytes) invalid = 0; invalid |= (STR0(str)[i] ^ padding); }
ef28c42014-07-22Henrik Grubbström (Grubba)  /* NB: If bytes <= 1 the loop will terminate before the * case where invalid is reset to zero is reached. */ if (bytes <= 1) invalid = 0;
83fe4f2014-04-30Henrik Grubbström (Grubba)  break; } if( m == PAD_ZERO ) { int c=THIS->block_size; while( str->str[len-1]==0 && c>0 ) { c--; len--; } } else len -= bytes; if (len < 0) Pike_error("String too short to unpad\n"); add_ref(str); pop_stack(); push_string(make_shared_binary_string(str->str, len)); free_string(str);
8b2ebd2014-07-21Henrik Grubbström (Grubba)  if( invalid )
83fe4f2014-04-30Henrik Grubbström (Grubba)  { pop_stack(); push_int(0); } } /*! @decl this_program set_iv(string(0..255) iv) *! Set the initialization vector to @[iv]. */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { apply(THIS->object, "set_iv", args); args = 1; RETURN this_object(); } } /*! @endclass State */
a48d7e2014-04-30Henrik Grubbström (Grubba)  /*! @decl State `()() *! *! @returns *! Returns a new @[State] object. */ PIKEFUN Nettle_BufferedCipher_cq__Buffer_State `()() { apply_current(Nettle_BufferedCipher_cq__Buffer_State_program_fun_num, args); }
83fe4f2014-04-30Henrik Grubbström (Grubba)  } /*! @endmodule Buffer */ INIT { apply_current(Nettle_BufferedCipher_cq__Buffer_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BUFFEREDCIPHER->Buffer = Pike_sp[-1].u.object); } pop_stack(); } } /*! @endclass BufferedCipher */ #define BUFFEREDCIPHER_CIPHER_INHERIT 1
3747282014-04-30Henrik Grubbström (Grubba) /*! @class BlockCipher *! *! Base class for all block ciphers. *!
83fe4f2014-04-30Henrik Grubbström (Grubba)  *! Extends the @[BufferedCipher] class with various operating modes.
3747282014-04-30Henrik Grubbström (Grubba)  */ PIKECLASS BlockCipher {
62a8ee2014-06-14Henrik Grubbström (Grubba)  /*! @decl inherit __builtin.Nettle.BlockCipher
3747282014-04-30Henrik Grubbström (Grubba)  */
62a8ee2014-06-14Henrik Grubbström (Grubba)  INHERIT "__builtin.Nettle.BlockCipher";
83fe4f2014-04-30Henrik Grubbström (Grubba)  /*! @decl inherit BufferedCipher
3747282014-04-30Henrik Grubbström (Grubba)  */
2194f92018-11-04Marcus Comstedt  INHERIT BufferedCipher;
3747282014-04-30Henrik Grubbström (Grubba) 
23225e2014-04-30Henrik Grubbström (Grubba)  /*! @module CBC
3230b82015-12-23Henrik Grubbström (Grubba)  *! Implementation of the Cipher Block Chaining mode (CBC).
23225e2014-04-30Henrik Grubbström (Grubba)  *! *! Works as a wrapper for the cipher implemented by overloading *! the parent class (@[Cipher]). *! *! @seealso *! @[Crypto.CBC], @[GCM] */
83fe4f2014-04-30Henrik Grubbström (Grubba)  PIKEVAR object(Nettle_BlockCipher_cq__CBC) CBC;
23225e2014-04-30Henrik Grubbström (Grubba)  PIKECLASS _CBC program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; {
83fe4f2014-04-30Henrik Grubbström (Grubba)  /*! @decl inherit BufferedCipher
23225e2014-04-30Henrik Grubbström (Grubba)  */
2194f92018-11-04Marcus Comstedt  INHERIT BufferedCipher;
23225e2014-04-30Henrik Grubbström (Grubba) 
9004d12014-05-11Henrik Grubbström (Grubba)  PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_name_fun_num, args);
9004d12014-05-11Henrik Grubbström (Grubba)  push_constant_text(".CBC"); f_add(2); } PIKEFUN int(1..) block_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args);
9004d12014-05-11Henrik Grubbström (Grubba)  } PIKEFUN int(1..) key_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_key_size_fun_num, args);
9004d12014-05-11Henrik Grubbström (Grubba)  } PIKEFUN int(0..) iv_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args);
9004d12014-05-11Henrik Grubbström (Grubba)  }
23225e2014-04-30Henrik Grubbström (Grubba)  /*! @class State */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { DOCSTART() @decl inherit Cipher::State DOCEND() EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the State class that our parent * contains via its inherit of Cipher via BufferedCipher.
23225e2014-04-30Henrik Grubbström (Grubba)  */
f35ab02017-08-02Martin Nilsson  lexical_inherit(1, MK_STRING("State"), 0, REPORT_ERROR);
23225e2014-04-30Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state;
1a31102014-05-13Henrik Grubbström (Grubba)  CVAR struct pike_string *iv; /* NB: Not finished. */
23225e2014-04-30Henrik Grubbström (Grubba)  CVAR INT32 block_size; CVAR INT32 mode; EXIT gc_trivial; {
40338f2017-07-10Martin Nilsson  if(THIS->iv)
1a31102014-05-13Henrik Grubbström (Grubba)  free_string(THIS->iv);
23225e2014-04-30Henrik Grubbström (Grubba)  }
2680122014-05-02Henrik Grubbström (Grubba)  /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; {
2194f92018-11-04Marcus Comstedt  apply_external(2, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  Nettle_Cipher_State_program_fun_num, 0);
2680122014-05-02Henrik Grubbström (Grubba)  }
23225e2014-04-30Henrik Grubbström (Grubba)  /*! @decl void create() *!
2680122014-05-02Henrik Grubbström (Grubba)  *! Initialize the CBC state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module.
23225e2014-04-30Henrik Grubbström (Grubba)  */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; unsigned old_block_size = THIS->block_size; unsigned block_size; int f;
2680122014-05-02Henrik Grubbström (Grubba)  apply_current(f_Nettle_BlockCipher_cq__CBC_State_substate_factory_fun_num, 0);
23225e2014-04-30Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); }
8c53732014-05-13Henrik Grubbström (Grubba)  apply(o, "block_size", 0);
23225e2014-04-30Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if ((!block_size) || (block_size > 4096)) Pike_error("Bad block size %d.\n", block_size); if(THIS->iv) {
1a31102014-05-13Henrik Grubbström (Grubba)  free_string(THIS->iv);
23225e2014-04-30Henrik Grubbström (Grubba)  THIS->iv = NULL; } THIS->block_size = block_size;
1a31102014-05-13Henrik Grubbström (Grubba)  THIS->iv = begin_shared_string(block_size);
21b12a2014-09-03Martin Nilsson  memset(STR0(THIS->iv), 0, block_size);
1a31102014-05-13Henrik Grubbström (Grubba)  THIS->iv->flags |= STRING_CLEAR_ON_EXIT;
23225e2014-04-30Henrik Grubbström (Grubba)  if (THIS->object) free_object(THIS->object); add_ref(THIS->object = o); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. * Check if the context and crypt function are valid. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits);
9b69512014-05-01Henrik Grubbström (Grubba)  } else { THIS->crypt_state = NULL;
65810c2017-12-28Martin Nilsson  } pop_n_elems(2);
23225e2014-04-30Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"CBC(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
5e9fc02015-08-18Per Hedbor  push_static_text("CBC(");
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "name", 0);
5e9fc02015-08-18Per Hedbor  push_static_text(")");
23225e2014-04-30Henrik Grubbström (Grubba)  f_add(3); }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) block_size()
23225e2014-04-30Henrik Grubbström (Grubba)  *! Returns the block size of the encapsulated cipher. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) block_size()
23225e2014-04-30Henrik Grubbström (Grubba)  optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) key_size()
23225e2014-04-30Henrik Grubbström (Grubba)  *! Returns the key size of the encapsulated cipher. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) key_size()
23225e2014-04-30Henrik Grubbström (Grubba)  optflags OPT_EXTERNAL_DEPEND; {
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "key_size", args); } /*! @decl int(1..) iv_size() *! Returns the size for the initialization vector */ PIKEFUN int(1..) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size;
23225e2014-04-30Henrik Grubbström (Grubba)  } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { assert(THIS->block_size); THIS->mode = 0; key->flags |= STRING_CLEAR_ON_EXIT;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_encrypt_key", args);
23225e2014-04-30Henrik Grubbström (Grubba)  pop_stack(); push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { assert(THIS->block_size); THIS->mode = 1; key->flags |= STRING_CLEAR_ON_EXIT;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_decrypt_key", args);
23225e2014-04-30Henrik Grubbström (Grubba)  pop_stack(); push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released. */ PIKEFUN object set_iv(string(0..255) 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");
59fc9e2014-09-03Martin Nilsson  memcpy(STR0(THIS->iv), STR0(iv), THIS->block_size);
23225e2014-04-30Henrik Grubbström (Grubba)  RETURN this_object(); } /*! @decl string(0..255) crypt(string(0..255) 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(0..255) data) { struct pike_string *result; ONERROR uwp;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
23225e2014-04-30Henrik Grubbström (Grubba)  void *ctx = THIS->object;
1a31102014-05-13Henrik Grubbström (Grubba)  struct pike_string *iv = THIS->iv;
0473d52014-05-11Henrik Grubbström (Grubba)  int block_size = THIS->block_size;
23225e2014-04-30Henrik Grubbström (Grubba)  NO_WIDE_STRING(data);
0473d52014-05-11Henrik Grubbström (Grubba)  if(data->len % block_size)
23225e2014-04-30Henrik Grubbström (Grubba)  Pike_error("Data length not multiple of block size.\n"); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } result = begin_shared_string(data->len); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; }
9b69512014-05-01Henrik Grubbström (Grubba)  if(THIS->mode == 0) {
0473d52014-05-11Henrik Grubbström (Grubba)  if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) {
1a31102014-05-13Henrik Grubbström (Grubba)  /* Protect the iv from being freed by a different thread. */ add_ref(iv);
0473d52014-05-11Henrik Grubbström (Grubba)  THREADS_ALLOW();
1a31102014-05-13Henrik Grubbström (Grubba)  cbc_encrypt(ctx, func, block_size, STR0(iv),
0473d52014-05-11Henrik Grubbström (Grubba)  data->len, STR0(result), STR0(data)); THREADS_DISALLOW();
1a31102014-05-13Henrik Grubbström (Grubba)  free_string(iv);
0473d52014-05-11Henrik Grubbström (Grubba)  } else {
1a31102014-05-13Henrik Grubbström (Grubba)  cbc_encrypt(ctx, func, block_size, STR0(iv),
0473d52014-05-11Henrik Grubbström (Grubba)  data->len, STR0(result), STR0(data)); }
9b69512014-05-01Henrik Grubbström (Grubba)  } else {
0473d52014-05-11Henrik Grubbström (Grubba)  if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) {
1a31102014-05-13Henrik Grubbström (Grubba)  /* Protect the iv from being freed by a different thread. */ add_ref(iv);
0473d52014-05-11Henrik Grubbström (Grubba)  THREADS_ALLOW();
1a31102014-05-13Henrik Grubbström (Grubba)  cbc_decrypt(ctx, func, block_size, STR0(iv),
0473d52014-05-11Henrik Grubbström (Grubba)  data->len, STR0(result), STR0(data)); THREADS_DISALLOW();
1a31102014-05-13Henrik Grubbström (Grubba)  free_string(iv);
0473d52014-05-11Henrik Grubbström (Grubba)  } else {
1a31102014-05-13Henrik Grubbström (Grubba)  cbc_decrypt(ctx, func, block_size, STR0(iv),
0473d52014-05-11Henrik Grubbström (Grubba)  data->len, STR0(result), STR0(data)); }
9b69512014-05-01Henrik Grubbström (Grubba)  } pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } } /*! @endclass State */ } /*! @endmodule CBC */
2ce2822014-06-02Henrik Grubbström (Grubba)  /*! @module PCBC
3230b82015-12-23Henrik Grubbström (Grubba)  *! Implementation of the Propagating Cipher Block Chaining mode (PCBC).
2ce2822014-06-02Henrik Grubbström (Grubba)  *!
9204652014-06-06Henrik Grubbström (Grubba)  *! This mode is also known as plaintext cipher block chaining (from *! Kerberos v4). *!
2ce2822014-06-02Henrik Grubbström (Grubba)  *! Works as a wrapper for the cipher implemented by overloading *! the parent class (@[Cipher]). *! *! @seealso *! @[CBC], @[GCM] */ PIKEVAR object(Nettle_BlockCipher_cq__PCBC) PCBC; PIKECLASS _PCBC program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; {
d62b782015-12-11Henrik Grubbström (Grubba)  /*! @decl inherit CBC
2ce2822014-06-02Henrik Grubbström (Grubba)  */ static int f_pcbc_inh_cbc_state_program_fun_num = -1; EXTRA { low_inherit(Nettle_BlockCipher_cq__CBC_program, 0, Nettle_BlockCipher_cq__CBC_program_fun_num, 42 + 1, 0, NULL); f_pcbc_inh_cbc_state_program_fun_num = really_low_reference_inherited_identifier(NULL, 1, Nettle_BlockCipher_cq__CBC_State_program_fun_num); } PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_name_fun_num, args);
2ce2822014-06-02Henrik Grubbström (Grubba)  push_constant_text(".PCBC"); f_add(2); } /*! @class State */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; {
d62b782015-12-11Henrik Grubbström (Grubba)  DOCSTART() @decl inherit CBC::State
2ce2822014-06-02Henrik Grubbström (Grubba)  DOCEND() static int f_pcbc_state_inh_cbc_state_crypt_fun_num = -1; EXTRA { low_inherit(Nettle_BlockCipher_cq__CBC_State_program, 0, f_pcbc_inh_cbc_state_program_fun_num, 42 + 1, 0, NULL); /* We want to call some of our inherited functions recursively... */ f_pcbc_state_inh_cbc_state_crypt_fun_num = really_low_reference_inherited_identifier(NULL, 1, f_Nettle_BlockCipher_cq__CBC_State_crypt_fun_num); } /*! @decl string(0..255) name() *! Returns the string @expr{"PCBC(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; { struct Nettle_BlockCipher_cq__CBC_State_struct *cbc_state = get_inherited_storage(1, Nettle_BlockCipher_cq__CBC_State_program); push_constant_text("PCBC("); apply(cbc_state->object, "name", 0); push_constant_text(")"); f_add(3); } /*! @decl string(0..255) crypt(string(0..255) data) *! *! Encrypt/decrypt @[data] and return the result. @[data] must *! be an integral number of blocks. *!
d62b782015-12-11Henrik Grubbström (Grubba)  *! Neither the input nor the output data is automatically memory
2ce2822014-06-02Henrik Grubbström (Grubba)  *! scrubbed, unless @[String.secure] has been called on the data. */ PIKEFUN string(0..255) crypt(string(0..255) data) { struct Nettle_BlockCipher_cq__CBC_State_struct *cbc_state = get_inherited_storage(1, Nettle_BlockCipher_cq__CBC_State_program); struct pike_string *propagated; ONERROR uwp; int block_size = cbc_state->block_size; NO_WIDE_STRING(data); if(data->len % block_size) { Pike_error("Data length not multiple of block size.\n"); } if (!cbc_state->object || !cbc_state->object->prog) { Pike_error("Lookup in destructed object.\n"); } if (!data->len) { return; } if (cbc_state->mode == 0) { propagated = begin_shared_string(data->len);
5f4b822014-06-06Henrik Grubbström (Grubba)  memcpy(STR0(propagated), STR0(data), block_size);
2ce2822014-06-02Henrik Grubbström (Grubba)  if (data->len > block_size) { memxor3(STR0(propagated) + block_size, STR0(data) + block_size, STR0(data), data->len - block_size); } pop_stack(); push_string(propagated); /* NB: Not shared! */ apply_current(f_pcbc_state_inh_cbc_state_crypt_fun_num, 1);
5f4b822014-06-06Henrik Grubbström (Grubba)  /* Update the iv with the last block of the plaintext. */ memxor(STR0(cbc_state->iv), STR0(data) + data->len - block_size, block_size);
2ce2822014-06-02Henrik Grubbström (Grubba)  } else { ptrdiff_t offset; apply_current(f_pcbc_state_inh_cbc_state_crypt_fun_num, 1); data = Pike_sp[-1].u.string;
5f4b822014-06-06Henrik Grubbström (Grubba)  if (data->len == block_size) { memxor(STR0(cbc_state->iv), STR0(data), block_size); return; }
2ce2822014-06-02Henrik Grubbström (Grubba)  propagated = begin_shared_string(data->len);
5f4b822014-06-06Henrik Grubbström (Grubba)  memcpy(STR0(propagated), STR0(data), block_size);
2ce2822014-06-02Henrik Grubbström (Grubba) 
5f4b822014-06-06Henrik Grubbström (Grubba)  for(offset = block_size; offset < data->len; offset += block_size) {
2ce2822014-06-02Henrik Grubbström (Grubba)  memxor3(STR0(propagated) + offset, STR0(data) + offset,
5f4b822014-06-06Henrik Grubbström (Grubba)  STR0(propagated) + offset - block_size, block_size);
2ce2822014-06-02Henrik Grubbström (Grubba)  }
5f4b822014-06-06Henrik Grubbström (Grubba)  memxor(STR0(cbc_state->iv), STR0(propagated) + offset - block_size, block_size);
2ce2822014-06-02Henrik Grubbström (Grubba)  pop_stack(); push_string(end_shared_string(propagated)); } } } /*! @endclass State */ } /*! @endmodule PCBC */
071f522015-12-14Henrik Grubbström (Grubba)  /*! @module IGE
3230b82015-12-23Henrik Grubbström (Grubba)  *! Implementation of the Infinite Garble Extension mode (IGE).
071f522015-12-14Henrik Grubbström (Grubba)  *!
fdbd022015-12-15Henrik Grubbström (Grubba)  *! This is a mode of operation suggested in 1977 by C. Cambell. *!
071f522015-12-14Henrik Grubbström (Grubba)  *! @seealso *! @[CBC], @[GCM], @[CFB] */ PIKEVAR object(Nettle_Cipher) IGE; PIKECLASS _IGE program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit BufferedCipher */
2194f92018-11-04Marcus Comstedt  INHERIT BufferedCipher;
071f522015-12-14Henrik Grubbström (Grubba)  PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
071f522015-12-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_name_fun_num, args); push_constant_text(".IGE"); f_add(2); } PIKEFUN int(1..) block_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
071f522015-12-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args); } PIKEFUN int(1..) key_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
071f522015-12-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_key_size_fun_num, args); } PIKEFUN int(0..) iv_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
071f522015-12-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args); push_int(2); f_multiply(2); } /*! @class State */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { DOCSTART() @decl inherit Cipher::State DOCEND() EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the State class that our parent * contains via its inherit of Cipher via BufferedCipher.
071f522015-12-14Henrik Grubbström (Grubba)  */
f35ab02017-08-02Martin Nilsson  lexical_inherit(1, MK_STRING("State"), 0, REPORT_ERROR);
071f522015-12-14Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state; CVAR struct pike_string *iv; /* NB: Not finished. */ CVAR INT32 block_size; /* NB: iv size is twice this. */ CVAR INT32 mode; EXIT gc_trivial; {
40338f2017-07-10Martin Nilsson  if(THIS->iv)
071f522015-12-14Henrik Grubbström (Grubba)  free_string(THIS->iv); } /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; {
2194f92018-11-04Marcus Comstedt  apply_external(2, Nettle_BlockCipher_BufferedCipher_inh_offset +
071f522015-12-14Henrik Grubbström (Grubba)  Nettle_Cipher_State_program_fun_num, 0); } /*! @decl void create() *! *! Initialize the IGE state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module. */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; unsigned old_block_size = THIS->block_size; unsigned block_size; int f; apply_current(f_Nettle_BlockCipher_cq__IGE_State_substate_factory_fun_num, 0); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); } apply(o, "block_size", 0); if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if ((!block_size) || (block_size > 4096)) Pike_error("Bad block size %d.\n", block_size); if(THIS->iv) { free_string(THIS->iv); THIS->iv = NULL; } THIS->block_size = block_size; THIS->iv = begin_shared_string(block_size * 2); memset(STR0(THIS->iv), 0, block_size * 2); THIS->iv->flags |= STRING_CLEAR_ON_EXIT; if (THIS->object) free_object(THIS->object); add_ref(THIS->object = o); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. * Check if the context and crypt function are valid. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits); } else { THIS->crypt_state = NULL;
65810c2017-12-28Martin Nilsson  } pop_n_elems(2);
071f522015-12-14Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"IGE(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; { push_static_text("IGE("); apply(THIS->object, "name", 0); push_static_text(")"); f_add(3); } /*! @decl int(1..) block_size() *! Returns the block size of the encapsulated cipher. */ PIKEFUN int(1..) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; } /*! @decl int(1..) key_size() *! Returns the key size of the encapsulated cipher. */ PIKEFUN int(1..) key_size() optflags OPT_EXTERNAL_DEPEND; { apply(THIS->object, "key_size", args); } /*! @decl int(1..) iv_size() *! Returns the size for the initialization vector */ PIKEFUN int(1..) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size * 2; } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { assert(THIS->block_size); THIS->mode = 0; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_encrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { assert(THIS->block_size); THIS->mode = 1; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_decrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released. *! *! @note *! IGE semantically has two initialization vectors of size *! @[block_size()]; @tt{x0@} (previous plaintext) and @tt{y0@} *! (previous ciphertext). They are here concatenated to a single *! initialization vector of double the block size. */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { assert(THIS->iv); iv->flags |= STRING_CLEAR_ON_EXIT; NO_WIDE_STRING(iv); if(iv->len != (THIS->block_size * 2)) Pike_error("Argument incompatible with cipher block size.\n"); memcpy(STR0(THIS->iv), STR0(iv), THIS->block_size); RETURN this_object(); } /*! @decl string(0..255) crypt(string(0..255) 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(0..255) data) { struct pike_string *result; ONERROR uwp; pike_nettle_crypt_func func = pike_crypt_func; void *ctx = THIS->object; struct pike_string *iv = THIS->iv; int block_size = THIS->block_size;
d3f15c2016-08-16Arne Goedeke  if (!data->len) return;
071f522015-12-14Henrik Grubbström (Grubba)  NO_WIDE_STRING(data); if(data->len % block_size) Pike_error("Data length not multiple of block size.\n"); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } result = begin_shared_string(data->len); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } if(THIS->mode == 0) { ptrdiff_t offset = 0; uint8_t *prev_dec = STR0(iv); uint8_t *prev_enc = prev_dec + block_size; uint8_t *res = STR0(result); uint8_t *src = STR0(data); if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* Protect the iv from being freed by a different thread. */ add_ref(iv); THREADS_ALLOW(); while (offset < data->len) { memxor3(res + offset, src + offset, prev_enc, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_dec, block_size); prev_dec = src + offset; prev_enc = res + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); THREADS_DISALLOW(); free_string(iv); } else { while (offset < data->len) { memxor3(res + offset, src + offset, prev_enc, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_dec, block_size); prev_dec = src + offset; prev_enc = res + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); } } else { ptrdiff_t offset = 0; uint8_t *prev_dec = STR0(iv); uint8_t *prev_enc = prev_dec + block_size; uint8_t *res = STR0(result); uint8_t *src = STR0(data); if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* Protect the iv from being freed by a different thread. */ add_ref(iv); THREADS_ALLOW(); while (offset < data->len) { memxor3(res + offset, src + offset, prev_dec, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_enc, block_size); prev_dec = res + offset; prev_enc = src + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); THREADS_DISALLOW(); free_string(iv); } else { while (offset < data->len) { memxor3(res + offset, src + offset, prev_dec, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_enc, block_size); prev_dec = res + offset; prev_enc = src + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); } } pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } } /*! @endclass State */ } /*! @endmodule IGE */
507bfd2015-12-21Henrik Grubbström (Grubba)  /*! @module ABC
3230b82015-12-23Henrik Grubbström (Grubba)  *! Implementation of the Accumulated Block Chaining mode (ABC).
507bfd2015-12-21Henrik Grubbström (Grubba)  *! *! This is a mode of operation similar to @[IGE], but *! where the plaintext is mixed with both initialization *! vectors. It was suggested as a mode of operation for *! @[AES] by Lars R. Knudsen. *! *! @seealso *! @[CBC], @[GCM], @[CFB], @[IGE] */ PIKEVAR object(Nettle_Cipher) ABC; PIKECLASS _ABC program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit BufferedCipher */
2194f92018-11-04Marcus Comstedt  INHERIT BufferedCipher;
507bfd2015-12-21Henrik Grubbström (Grubba)  PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
507bfd2015-12-21Henrik Grubbström (Grubba)  f_Nettle_Cipher_name_fun_num, args); push_constant_text(".ABC"); f_add(2); } PIKEFUN int(1..) block_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
507bfd2015-12-21Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args); } PIKEFUN int(1..) key_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
507bfd2015-12-21Henrik Grubbström (Grubba)  f_Nettle_Cipher_key_size_fun_num, args); } PIKEFUN int(0..) iv_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
507bfd2015-12-21Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args); push_int(2); f_multiply(2); } /*! @class State */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { DOCSTART() @decl inherit Cipher::State DOCEND() EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the State class that our parent * contains via its inherit of Cipher via BufferedCipher.
507bfd2015-12-21Henrik Grubbström (Grubba)  */
f35ab02017-08-02Martin Nilsson  lexical_inherit(1, MK_STRING("State"), 0, REPORT_ERROR);
507bfd2015-12-21Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state; CVAR struct pike_string *iv; /* NB: Not finished. */ CVAR INT32 block_size; /* NB: iv size is twice this. */ CVAR INT32 mode; EXIT gc_trivial; {
40338f2017-07-10Martin Nilsson  if(THIS->iv)
507bfd2015-12-21Henrik Grubbström (Grubba)  free_string(THIS->iv); } /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; {
2194f92018-11-04Marcus Comstedt  apply_external(2, Nettle_BlockCipher_BufferedCipher_inh_offset +
507bfd2015-12-21Henrik Grubbström (Grubba)  Nettle_Cipher_State_program_fun_num, 0); } /*! @decl void create() *! *! Initialize the ABC state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module. */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; unsigned old_block_size = THIS->block_size; unsigned block_size; int f; apply_current(f_Nettle_BlockCipher_cq__ABC_State_substate_factory_fun_num, 0); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); } apply(o, "block_size", 0); if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if ((!block_size) || (block_size > 4096)) Pike_error("Bad block size %d.\n", block_size); if(THIS->iv) { free_string(THIS->iv); THIS->iv = NULL; } THIS->block_size = block_size; THIS->iv = begin_shared_string(block_size * 2); memset(STR0(THIS->iv), 0, block_size * 2); THIS->iv->flags |= STRING_CLEAR_ON_EXIT; if (THIS->object) free_object(THIS->object); add_ref(THIS->object = o); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. * Check if the context and crypt function are valid. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits); } else { THIS->crypt_state = NULL;
65810c2017-12-28Martin Nilsson  } pop_n_elems(2);
507bfd2015-12-21Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"ABC(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; { push_static_text("ABC("); apply(THIS->object, "name", 0); push_static_text(")"); f_add(3); } /*! @decl int(1..) block_size() *! Returns the block size of the encapsulated cipher. */ PIKEFUN int(1..) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; } /*! @decl int(1..) key_size() *! Returns the key size of the encapsulated cipher. */ PIKEFUN int(1..) key_size() optflags OPT_EXTERNAL_DEPEND; { apply(THIS->object, "key_size", args); } /*! @decl int(1..) iv_size() *! Returns the size for the initialization vector */ PIKEFUN int(1..) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size * 2; } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { assert(THIS->block_size); THIS->mode = 0; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_encrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { assert(THIS->block_size); THIS->mode = 1; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_decrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released. *! *! @note *! ABC semantically has two initialization vectors of size *! @[block_size()]; @tt{x0@} (previous plaintext) and @tt{y0@} *! (previous ciphertext). They are here concatenated to a single *! initialization vector of double the block size. */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { assert(THIS->iv); iv->flags |= STRING_CLEAR_ON_EXIT; NO_WIDE_STRING(iv); if(iv->len != (THIS->block_size * 2)) Pike_error("Argument incompatible with cipher block size.\n"); memcpy(STR0(THIS->iv), STR0(iv), THIS->block_size); RETURN this_object(); } /*! @decl string(0..255) crypt(string(0..255) 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(0..255) data) { struct pike_string *result; ONERROR uwp; pike_nettle_crypt_func func = pike_crypt_func; void *ctx = THIS->object; struct pike_string *iv = THIS->iv; int block_size = THIS->block_size; NO_WIDE_STRING(data);
1375c12016-07-29Arne Goedeke  if (!data->len) return;
507bfd2015-12-21Henrik Grubbström (Grubba)  if(data->len % block_size) Pike_error("Data length not multiple of block size.\n"); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } result = begin_shared_string(data->len); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } if(THIS->mode == 0) { ptrdiff_t offset = 0; uint8_t *prev_dec = STR0(iv); uint8_t *prev_enc = prev_dec + block_size; uint8_t *res = STR0(result); uint8_t *src = STR0(data); if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* Protect the iv from being freed by a different thread. */ add_ref(iv); THREADS_ALLOW(); while (offset < data->len) { memxor3(res + offset, src + offset, prev_enc, block_size); memrolx(res + offset, prev_dec, 1, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_dec, block_size); prev_dec = src + offset; prev_enc = res + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); THREADS_DISALLOW(); free_string(iv); } else { while (offset < data->len) { memxor3(res + offset, src + offset, prev_enc, block_size); memrolx(res + offset, prev_dec, 1, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_dec, block_size); prev_dec = src + offset; prev_enc = res + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); } } else { ptrdiff_t offset = 0; uint8_t *prev_dec = STR0(iv); uint8_t *prev_enc = prev_dec + block_size; uint8_t *res = STR0(result); uint8_t *src = STR0(data); if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* Protect the iv from being freed by a different thread. */ add_ref(iv); THREADS_ALLOW(); while (offset < data->len) { memxor3(res + offset, src + offset, prev_dec, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_enc, block_size); memrolx(res + offset, prev_dec, 1, block_size); prev_dec = res + offset; prev_enc = src + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); THREADS_DISALLOW(); free_string(iv); } else { while (offset < data->len) { memxor3(res + offset, src + offset, prev_dec, block_size); func(ctx, block_size, res + offset, res + offset); memxor(res + offset, prev_enc, block_size); memrolx(res + offset, prev_dec, 1, block_size); prev_dec = res + offset; prev_enc = src + offset; offset += block_size; } memcpy(STR0(iv), prev_dec, block_size); memcpy(STR0(iv) + block_size, prev_enc, block_size); } } pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } } /*! @endclass State */ } /*! @endmodule ABC */
8ea8d52014-06-07Henrik Grubbström (Grubba)  /*! @module CFB
3230b82015-12-23Henrik Grubbström (Grubba)  *! Implementation of the Cipher Feed-Back mode (CFB).
8ea8d52014-06-07Henrik Grubbström (Grubba)  *! *! @seealso *! @[CBC], @[GCM] */ PIKEVAR object(Nettle_Cipher) CFB; PIKECLASS _CFB program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit BufferedCipher */
2194f92018-11-04Marcus Comstedt  INHERIT BufferedCipher;
8ea8d52014-06-07Henrik Grubbström (Grubba)  /*! @decl string(0..255) name() *! Returns the base cipher name appended with the string @expr{".CFB"@}. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_name_fun_num, args);
5e9fc02015-08-18Per Hedbor  push_static_text(".CFB");
8ea8d52014-06-07Henrik Grubbström (Grubba)  f_add(2); } PIKEFUN int(1..) block_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } PIKEFUN int(1..) key_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_key_size_fun_num, args);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } PIKEFUN int(0..) iv_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } /*! @class State *! *! The state for a CFB instance. */ PIKECLASS State program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT; { DOCSTART() @decl inherit BufferedCipher::State DOCEND() EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the State class that our parent * contains via its inherit of Cipher via BufferedCipher.
8ea8d52014-06-07Henrik Grubbström (Grubba)  */
f35ab02017-08-02Martin Nilsson  lexical_inherit(1, MK_STRING("State"), 0, REPORT_ERROR);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state; CVAR struct pike_string *iv; /* NB: Not finished. */ CVAR INT32 block_size; CVAR INT32 mode; EXIT gc_trivial; {
40338f2017-07-10Martin Nilsson  if (THIS->iv)
8ea8d52014-06-07Henrik Grubbström (Grubba)  free_string(THIS->iv); } /*! @decl object `obj() *! *! Getter for the wrapped cipher algorithm. */ PIKEFUN object `obj() { if (THIS->object) { ref_push_object(THIS->object); } else { push_int(0); } } /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; {
2194f92018-11-04Marcus Comstedt  apply_external(2, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  Nettle_Cipher_State_program_fun_num, 0);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } /*! @decl void create() *! *! Initialize the CFB state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module. */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; int old_block_size = THIS->block_size; int block_size; int f; if (THIS->object) free_object(THIS->object); THIS->object = NULL; THIS->crypt_state = NULL; apply_current(f_Nettle_BlockCipher_cq__CFB_State_substate_factory_fun_num, 0); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); } apply(o, "block_size", 0); if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer;
d69c232014-10-23Arne Goedeke  if ((block_size <= 0) || (block_size > 4096))
8ea8d52014-06-07Henrik Grubbström (Grubba)  Pike_error("Bad block size %d.\n", block_size); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. * Check if the context and crypt function are valid. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits); } if(THIS->iv) { free_string(THIS->iv); THIS->iv = NULL; } THIS->iv = begin_shared_string(block_size);
21b12a2014-09-03Martin Nilsson  memset(STR0(THIS->iv), 0, block_size);
8ea8d52014-06-07Henrik Grubbström (Grubba)  THIS->iv->flags |= STRING_CLEAR_ON_EXIT; THIS->block_size = block_size; THIS->mode = 0;
65810c2017-12-28Martin Nilsson  add_ref(THIS->object = o); pop_n_elems(2);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"CFB(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
5e9fc02015-08-18Per Hedbor  push_static_text("CFB(");
8ea8d52014-06-07Henrik Grubbström (Grubba)  apply(THIS->object, "name", 0);
5e9fc02015-08-18Per Hedbor  push_static_text(")");
8ea8d52014-06-07Henrik Grubbström (Grubba)  f_add(3); } /*! @decl int(1..) block_size() *! Returns the block size of the encapsulated cipher. */ PIKEFUN int(1..) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; } /*! @decl int(1..) iv_size() *! Returns the size for the initialization vector */ PIKEFUN int(1..) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; } /*! @decl int(1..) key_size() *! Returns the key size of the encapsulated cipher. */ PIKEFUN int(1..) key_size() optflags OPT_EXTERNAL_DEPEND; { apply(THIS->object, "key_size", args); } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for encrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_decrypt_key()], @[set_iv()] */ PIKEFUN object set_encrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
8ea8d52014-06-07Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_encrypt_key", args); pop_stack(); THIS->mode = 0; push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for decrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_encrypt_key()], @[set_iv()] */ PIKEFUN object set_decrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
8ea8d52014-06-07Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; /* NOTE: CFB always uses the encryption function * of the underlying cipher! */ apply(THIS->object, "set_encrypt_key", args); pop_stack(); THIS->mode = 1; push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released. *! *! @note *! @[iv] must have the length reported by @[iv_size()]. *! *! @seealso *! @[set_encrypt_key()], @[set_decrypt_key()]. */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { 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");
59fc9e2014-09-03Martin Nilsson  memcpy(STR0(THIS->iv), STR0(iv), THIS->block_size);
8ea8d52014-06-07Henrik Grubbström (Grubba)  RETURN this_object(); } /*! @decl string(0..255) crypt(string(0..255) data) *! *! Encrypt/decrypt @[data] and return the result. @[data] must *! be an integral number of blocks. *! *! The length of @[data] MUST be a multiple of the block size *! for all calls except the last. *! *! Neither the input or output data is not automatically memory *! scrubbed, unless @[String.secure] has been called on the data. *! *! @seealso *! @[update()], @[digest()] */ PIKEFUN string(0..255) crypt(string(0..255) data) { struct pike_string *result; ONERROR uwp;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
8ea8d52014-06-07Henrik Grubbström (Grubba)  void *ctx = THIS->object; struct pike_string *iv = THIS->iv;
0695b42014-11-05Martin Nilsson  unsigned block_size = (unsigned)THIS->block_size;
8ea8d52014-06-07Henrik Grubbström (Grubba)  NO_WIDE_STRING(data); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } if (!data->len) return; result = begin_shared_string(data->len); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } if (!THIS->mode) { /* Encryption. */ const uint8_t *prev = STR0(iv); uint8_t *src = STR0(data); uint8_t *dst = STR0(result); pike_nettle_size_t bytes = data->len; if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* Protect the iv from being freed by a different thread. */ add_ref(iv); THREADS_ALLOW();
2a17082014-06-13Henrik Grubbström (Grubba)  while (bytes >= block_size) {
8ea8d52014-06-07Henrik Grubbström (Grubba)  func(ctx, block_size, STR0(iv), prev); memxor3(dst, STR0(iv), src, block_size); prev = dst; dst += block_size; src += block_size; bytes -= block_size; }
2a17082014-06-13Henrik Grubbström (Grubba)  if (!bytes) { memcpy(STR0(iv), dst - block_size, block_size); } else { /* Trailer partial block. */ func(ctx, block_size, STR0(iv), prev); memxor3(dst, STR0(iv), src, bytes); memcpy(STR0(iv), dst, bytes); }
8ea8d52014-06-07Henrik Grubbström (Grubba)  THREADS_DISALLOW(); free_string(iv); } else {
2a17082014-06-13Henrik Grubbström (Grubba)  while (bytes >= block_size) {
8ea8d52014-06-07Henrik Grubbström (Grubba)  func(ctx, block_size, STR0(iv), prev); memxor3(dst, STR0(iv), src, block_size); prev = dst; dst += block_size; src += block_size; bytes -= block_size; }
2a17082014-06-13Henrik Grubbström (Grubba)  if (!bytes) { memcpy(STR0(iv), dst - block_size, block_size); } else { /* Trailer partial block. */ func(ctx, block_size, STR0(iv), prev); memxor3(dst, STR0(iv), src, bytes); memcpy(STR0(iv), dst, bytes); }
8ea8d52014-06-07Henrik Grubbström (Grubba)  } } else { /* Decryption. */
0695b42014-11-05Martin Nilsson  unsigned trailer_len = data->len % block_size; unsigned blocked_len = data->len - trailer_len;
8ea8d52014-06-07Henrik Grubbström (Grubba)  if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* Protect the iv from being freed by a different thread. */ add_ref(iv); THREADS_ALLOW();
2a17082014-06-13Henrik Grubbström (Grubba)  if (blocked_len) { memcpy(STR0(result), STR0(iv), block_size); if (blocked_len > block_size) { memcpy(STR0(result) + block_size, STR0(data), blocked_len - block_size); } func(ctx, blocked_len, STR0(result), STR0(result)); memxor(STR0(result), STR0(data), blocked_len); memcpy(STR0(iv), STR0(data) + blocked_len - block_size, block_size); } if (trailer_len) { func(ctx, block_size, STR0(iv), STR0(iv)); memxor3(STR0(result) + blocked_len, STR0(data) + blocked_len, STR0(iv), trailer_len); memcpy(STR0(iv), STR0(data) + blocked_len, trailer_len);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } THREADS_DISALLOW(); free_string(iv); } else {
2a17082014-06-13Henrik Grubbström (Grubba)  if (blocked_len) { memcpy(STR0(result), STR0(iv), block_size); if (blocked_len > block_size) { memcpy(STR0(result) + block_size, STR0(data), blocked_len - block_size); } func(ctx, blocked_len, STR0(result), STR0(result)); memxor(STR0(result), STR0(data), blocked_len); memcpy(STR0(iv), STR0(data) + blocked_len - block_size, block_size); } if (trailer_len) { func(ctx, block_size, STR0(iv), STR0(iv)); memxor3(STR0(result) + blocked_len, STR0(data) + blocked_len, STR0(iv), trailer_len); memcpy(STR0(iv), STR0(data) + blocked_len, trailer_len);
8ea8d52014-06-07Henrik Grubbström (Grubba)  } } } pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } } /*! @endclass */ /*! @decl State `()() *! *! @returns *! Returns a new @[State] object. */ PIKEFUN Nettle_Cipher_State `()() { apply_current(Nettle_BlockCipher_cq__CFB_State_program_fun_num, args); } }
b631ad2014-06-15Henrik Grubbström (Grubba)  /*! @endmodule CFB
8ea8d52014-06-07Henrik Grubbström (Grubba)  */
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @module CTR
3230b82015-12-23Henrik Grubbström (Grubba)  *! Implementation of the Counter mode (CTR).
9b69512014-05-01Henrik Grubbström (Grubba)  *! *! This cipher mode works like a stream cipher with *! a block size >= 1. This means that the same key *! and initialization vector (aka counter) should *! never be reused, since a simple xor would reveal *! information about the plain text. It also means *! that it should never be used without a suiteable *! Message Authentication Code (MAC). *! *! @seealso *! @[CBC], @[GCM], @[Buffer] */ PIKEVAR object(Nettle_Cipher) CTR; PIKECLASS _CTR program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit __builtin.Nettle.Cipher */ INHERIT "__builtin.Nettle.Cipher"; /*! @decl string(0..255) name()
9004d12014-05-11Henrik Grubbström (Grubba)  *! Returns the base cipher name appended with the string @expr{".CTR"@}.
9b69512014-05-01Henrik Grubbström (Grubba)  */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_name_fun_num, args);
5e9fc02015-08-18Per Hedbor  push_static_text(".CTR");
9004d12014-05-11Henrik Grubbström (Grubba)  f_add(2); } PIKEFUN int(1..) block_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args);
9004d12014-05-11Henrik Grubbström (Grubba)  } PIKEFUN int(1..) key_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_key_size_fun_num, args);
9004d12014-05-11Henrik Grubbström (Grubba)  } PIKEFUN int(0..) iv_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args);
9b69512014-05-01Henrik Grubbström (Grubba)  } /*! @class State *! *! The state for a CTR instance. */ PIKECLASS State
9e336b2014-06-19Henrik Grubbström (Grubba)  program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;
9b69512014-05-01Henrik Grubbström (Grubba)  { DOCSTART() @decl inherit Cipher::State DOCEND() EXTRA { /* Perform an inherit of the State class (if any) that our parent * may contain via its inherit of __builtin.Nettle.Cipher. */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
9b69512014-05-01Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state;
1a31102014-05-13Henrik Grubbström (Grubba)  CVAR struct pike_string *iv; /* NB: Not finished. */
9b69512014-05-01Henrik Grubbström (Grubba)  CVAR INT32 block_size; EXIT gc_trivial; {
40338f2017-07-10Martin Nilsson  if (THIS->iv)
1a31102014-05-13Henrik Grubbström (Grubba)  free_string(THIS->iv);
9b69512014-05-01Henrik Grubbström (Grubba)  } /*! @decl object `obj() *! *! Getter for the wrapped cipher algorithm. */ PIKEFUN object `obj() { if (THIS->object) { ref_push_object(THIS->object); } else { push_int(0); } }
2680122014-05-02Henrik Grubbström (Grubba)  /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; {
2194f92018-11-04Marcus Comstedt  apply_external(2, Nettle_BlockCipher_BufferedCipher_inh_offset +
62a8ee2014-06-14Henrik Grubbström (Grubba)  Nettle_Cipher_State_program_fun_num, 0);
2680122014-05-02Henrik Grubbström (Grubba)  }
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @decl void create() *!
2680122014-05-02Henrik Grubbström (Grubba)  *! Initialize the CTR state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module.
9b69512014-05-01Henrik Grubbström (Grubba)  */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; int old_block_size = THIS->block_size; int block_size; int f; if (THIS->object) free_object(THIS->object);
1a31102014-05-13Henrik Grubbström (Grubba)  THIS->object = NULL;
9b69512014-05-01Henrik Grubbström (Grubba)  THIS->crypt_state = NULL;
2680122014-05-02Henrik Grubbström (Grubba)  apply_current(f_Nettle_BlockCipher_cq__CTR_State_substate_factory_fun_num, 0);
9b69512014-05-01Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); }
8c53732014-05-13Henrik Grubbström (Grubba)  apply(o, "block_size", 0);
9b69512014-05-01Henrik Grubbström (Grubba)  if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if ((!block_size) || (block_size > 4096)) Pike_error("Bad block size %d.\n", block_size); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. * Check if the context and crypt function are valid. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits); } if(THIS->iv) {
1a31102014-05-13Henrik Grubbström (Grubba)  free_string(THIS->iv);
9b69512014-05-01Henrik Grubbström (Grubba)  THIS->iv = NULL; }
1a31102014-05-13Henrik Grubbström (Grubba)  THIS->iv = begin_shared_string(block_size);
21b12a2014-09-03Martin Nilsson  memset(STR0(THIS->iv), 0, block_size);
1a31102014-05-13Henrik Grubbström (Grubba)  THIS->iv->flags |= STRING_CLEAR_ON_EXIT;
9b69512014-05-01Henrik Grubbström (Grubba)  THIS->block_size = block_size;
1f87562018-01-01Martin Nilsson  add_ref(THIS->object = o); pop_n_elems(2);
9b69512014-05-01Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"CTR(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
5e9fc02015-08-18Per Hedbor  push_static_text("CTR(");
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "name", 0);
5e9fc02015-08-18Per Hedbor  push_static_text(")");
9b69512014-05-01Henrik Grubbström (Grubba)  f_add(3); } /*! @decl int(1..) block_size() *! Returns the block size of the encapsulated cipher. */ PIKEFUN int(1..) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; } /*! @decl int(1..) iv_size() *! Returns the size for the initialization vector */ PIKEFUN int(1..) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) key_size()
9b69512014-05-01Henrik Grubbström (Grubba)  *! Returns the key size of the encapsulated cipher. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) key_size()
9b69512014-05-01Henrik Grubbström (Grubba)  optflags OPT_EXTERNAL_DEPEND; {
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "key_size", args);
9b69512014-05-01Henrik Grubbström (Grubba)  } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for encrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_decrypt_key()], @[set_iv()] */ PIKEFUN object set_encrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9b69512014-05-01Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_encrypt_key", args);
9b69512014-05-01Henrik Grubbström (Grubba)  pop_stack(); push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for decrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_encrypt_key()], @[set_iv()] */ PIKEFUN object set_decrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9b69512014-05-01Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; /* NOTE: CTR always uses the encryption function * of the underlying cipher! */
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_encrypt_key", args);
9b69512014-05-01Henrik Grubbström (Grubba)  pop_stack(); push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released. *! *! @note *! @[iv] must have the length reported by @[iv_size()]. *! *! @seealso *! @[set_encrypt_key()], @[set_decrypt_key()]. */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { 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");
59fc9e2014-09-03Martin Nilsson  memcpy(STR0(THIS->iv), STR0(iv), THIS->block_size);
9b69512014-05-01Henrik Grubbström (Grubba)  RETURN this_object(); } /*! @decl string(0..255) crypt(string(0..255) data) *! *! Encrypt/decrypt @[data] and return the result. @[data] must *! be an integral number of blocks. *! *! The length of @[data] MUST be a multiple of the block size *! for all calls except the last. *! *! Neither the input or output data is not automatically memory *! scrubbed, unless @[String.secure] has been called on the data. *! *! @seealso *! @[update()], @[digest()] */ PIKEFUN string(0..255) crypt(string(0..255) data) { struct pike_string *result; ONERROR uwp;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9b69512014-05-01Henrik Grubbström (Grubba)  void *ctx = THIS->object;
1a31102014-05-13Henrik Grubbström (Grubba)  struct pike_string *iv = THIS->iv;
0473d52014-05-11Henrik Grubbström (Grubba)  int block_size = THIS->block_size;
9b69512014-05-01Henrik Grubbström (Grubba)  NO_WIDE_STRING(data); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } result = begin_shared_string(data->len); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; }
0473d52014-05-11Henrik Grubbström (Grubba)  if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) {
1a31102014-05-13Henrik Grubbström (Grubba)  /* Protect the iv from being freed by a different thread. */ add_ref(iv);
0473d52014-05-11Henrik Grubbström (Grubba)  THREADS_ALLOW();
1a31102014-05-13Henrik Grubbström (Grubba)  ctr_crypt(ctx, func, block_size, STR0(iv),
0473d52014-05-11Henrik Grubbström (Grubba)  data->len, STR0(result), STR0(data)); THREADS_DISALLOW();
1a31102014-05-13Henrik Grubbström (Grubba)  free_string(iv);
0473d52014-05-11Henrik Grubbström (Grubba)  } else {
1a31102014-05-13Henrik Grubbström (Grubba)  ctr_crypt(ctx, func, block_size, STR0(iv),
0473d52014-05-11Henrik Grubbström (Grubba)  data->len, STR0(result), STR0(data)); }
9b69512014-05-01Henrik Grubbström (Grubba)  pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } } /*! @endclass */ /*! @decl State `()() *! *! @returns *! Returns a new @[State] object. */ PIKEFUN Nettle_Cipher_State `()() { apply_current(Nettle_BlockCipher_cq__CTR_State_program_fun_num, args); } } /*! @endmodule CTR */
b631ad2014-06-15Henrik Grubbström (Grubba)  /*! @module OFB
3230b82015-12-23Henrik Grubbström (Grubba)  *! Implementation of the Output Feed-Back mode (OFB).
b631ad2014-06-15Henrik Grubbström (Grubba)  *! *! This cipher mode works like a stream cipher with *! a block size >= 1. This means that the same key *! and initialization vector (aka counter) should *! never be reused, since a simple xor would reveal *! information about the plain text. It also means *! that it should never be used without a suiteable *! Message Authentication Code (MAC). *! *! @seealso *! @[CFB], @[CBC], @[CTR], @[GCM] */ PIKEVAR object(Nettle_Cipher) OFB; PIKECLASS _OFB program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit BufferedCipher */
2194f92018-11-04Marcus Comstedt  INHERIT BufferedCipher;
b631ad2014-06-15Henrik Grubbström (Grubba)  /*! @decl string(0..255) name() *! Returns the base cipher name appended with the string @expr{".OFB"@}. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
b631ad2014-06-15Henrik Grubbström (Grubba)  f_Nettle_Cipher_name_fun_num, args);
5e9fc02015-08-18Per Hedbor  push_static_text(".OFB");
b631ad2014-06-15Henrik Grubbström (Grubba)  f_add(2); } PIKEFUN int(1..) block_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
b631ad2014-06-15Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args); } PIKEFUN int(1..) key_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
b631ad2014-06-15Henrik Grubbström (Grubba)  f_Nettle_Cipher_key_size_fun_num, args); } PIKEFUN int(0..) iv_size() {
2194f92018-11-04Marcus Comstedt  apply_external(1, Nettle_BlockCipher_BufferedCipher_inh_offset +
b631ad2014-06-15Henrik Grubbström (Grubba)  f_Nettle_Cipher_block_size_fun_num, args); } /*! @class State *! *! The state for a OFB instance. */ PIKECLASS State program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT; { DOCSTART() @decl inherit BufferedCipher::State DOCEND() EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the State class that our parent * contains via its inherit of Cipher via BufferedCipher.
b631ad2014-06-15Henrik Grubbström (Grubba)  */
f35ab02017-08-02Martin Nilsson  lexical_inherit(1, MK_STRING("State"), 0, REPORT_ERROR);
b631ad2014-06-15Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state; CVAR struct pike_string *iv; /* NB: Not finished. */ CVAR INT32 block_size; EXIT gc_trivial; {
40338f2017-07-10Martin Nilsson  if (THIS->iv)
b631ad2014-06-15Henrik Grubbström (Grubba)  free_string(THIS->iv); } /*! @decl object `obj() *! *! Getter for the wrapped cipher algorithm. */ PIKEFUN object `obj() { if (THIS->object) { ref_push_object(THIS->object); } else { push_int(0); } } /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; {
2194f92018-11-04Marcus Comstedt  apply_external(2, Nettle_BlockCipher_BufferedCipher_inh_offset +
b631ad2014-06-15Henrik Grubbström (Grubba)  Nettle_Cipher_State_program_fun_num, 0); } /*! @decl void create() *! *! Initialize the OFB state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module. */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; int old_block_size = THIS->block_size; int block_size; int f; if (THIS->object) free_object(THIS->object); THIS->object = NULL; THIS->crypt_state = NULL; apply_current(f_Nettle_BlockCipher_cq__OFB_State_substate_factory_fun_num, 0); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); } apply(o, "block_size", 0); if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if ((!block_size) || (block_size > 4096)) Pike_error("Bad block size %d.\n", block_size); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. * Check if the context and crypt function are valid. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits); } if(THIS->iv) { free_string(THIS->iv); THIS->iv = NULL; } THIS->iv = begin_shared_string(block_size);
21b12a2014-09-03Martin Nilsson  memset(STR0(THIS->iv), 0, block_size);
b631ad2014-06-15Henrik Grubbström (Grubba)  THIS->iv->flags |= STRING_CLEAR_ON_EXIT; THIS->block_size = block_size;
1f87562018-01-01Martin Nilsson  add_ref(THIS->object = o); pop_n_elems(2);
b631ad2014-06-15Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"OFB(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
5e9fc02015-08-18Per Hedbor  push_static_text("OFB(");
b631ad2014-06-15Henrik Grubbström (Grubba)  apply(THIS->object, "name", 0);
5e9fc02015-08-18Per Hedbor  push_static_text(")");
b631ad2014-06-15Henrik Grubbström (Grubba)  f_add(3); } /*! @decl int(1..) block_size() *! Returns the block size of the encapsulated cipher. */ PIKEFUN int(1..) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; } /*! @decl int(1..) iv_size() *! Returns the size for the initialization vector */ PIKEFUN int(1..) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN THIS->block_size; } /*! @decl int(1..) key_size() *! Returns the key size of the encapsulated cipher. */ PIKEFUN int(1..) key_size() optflags OPT_EXTERNAL_DEPEND; { apply(THIS->object, "key_size", args); } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for encrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_decrypt_key()], @[set_iv()] */ PIKEFUN object set_encrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
b631ad2014-06-15Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_encrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for decrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_encrypt_key()], @[set_iv()] */ PIKEFUN object set_decrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
b631ad2014-06-15Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; /* NOTE: OFB always uses the encryption function * of the underlying cipher! */ apply(THIS->object, "set_encrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released. *! *! @note *! @[iv] must have the length reported by @[iv_size()]. *! *! @seealso *! @[set_encrypt_key()], @[set_decrypt_key()]. */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { 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");
59fc9e2014-09-03Martin Nilsson  memcpy(STR0(THIS->iv), STR0(iv), THIS->block_size);
b631ad2014-06-15Henrik Grubbström (Grubba)  RETURN this_object(); } /*! @decl string(0..255) crypt(string(0..255) data) *! *! Encrypt/decrypt @[data] and return the result. @[data] must *! be an integral number of blocks. *! *! The length of @[data] MUST be a multiple of the block size *! for all calls except the last. *! *! Neither the input or output data is not automatically memory *! scrubbed, unless @[String.secure] has been called on the data. *! *! @seealso *! @[update()], @[digest()] */ PIKEFUN string(0..255) crypt(string(0..255) data) { struct pike_string *result; ONERROR uwp;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
b631ad2014-06-15Henrik Grubbström (Grubba)  void *ctx = THIS->object; struct pike_string *iv = THIS->iv;
0695b42014-11-05Martin Nilsson  unsigned block_size = (unsigned)THIS->block_size;
b631ad2014-06-15Henrik Grubbström (Grubba)  uint8_t *src; uint8_t *dst; pike_nettle_size_t bytes; NO_WIDE_STRING(data); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } if (!(bytes = data->len)) return; result = begin_shared_string(data->len); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } src = STR0(data); dst = STR0(result); if ((bytes >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* Protect the iv from being freed by a different thread. */ add_ref(iv); THREADS_ALLOW(); while (bytes >= block_size) { func(ctx, block_size, STR0(iv), STR0(iv)); memxor3(dst, STR0(iv), src, block_size); dst += block_size; src += block_size; bytes -= block_size; } if (bytes) { func(ctx, block_size, STR0(iv), STR0(iv)); memxor3(dst, STR0(iv), src, bytes); } THREADS_DISALLOW(); free_string(iv); } else { while (bytes >= block_size) { func(ctx, block_size, STR0(iv), STR0(iv)); memxor3(dst, STR0(iv), src, block_size); dst += block_size; src += block_size; bytes -= block_size; } if (bytes) { func(ctx, block_size, STR0(iv), STR0(iv)); memxor3(dst, STR0(iv), src, bytes); } } pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } } /*! @endclass */ /*! @decl State `()() *! *! @returns *! Returns a new @[State] object. */ PIKEFUN Nettle_Cipher_State `()() { apply_current(Nettle_BlockCipher_cq__OFB_State_program_fun_num, args); } } /*! @endmodule OFB */ /* NB: Declare the storage explicitly to avoid having it declared * inside the #ifdef above. */ DECLARE_STORAGE;
9b69512014-05-01Henrik Grubbström (Grubba)  INIT { apply_current(Nettle_BlockCipher_cq__CBC_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER->CBC = Pike_sp[-1].u.object); } pop_stack();
2ce2822014-06-02Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher_cq__PCBC_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER->PCBC = Pike_sp[-1].u.object); } pop_stack();
071f522015-12-14Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher_cq__IGE_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER->IGE = Pike_sp[-1].u.object); } pop_stack();
507bfd2015-12-21Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher_cq__ABC_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER->ABC = Pike_sp[-1].u.object); } pop_stack();
8ea8d52014-06-07Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher_cq__CFB_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER->CFB = Pike_sp[-1].u.object); } pop_stack();
9b69512014-05-01Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher_cq__CTR_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER->CTR = Pike_sp[-1].u.object); } pop_stack();
b631ad2014-06-15Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher_cq__OFB_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER->OFB = Pike_sp[-1].u.object); } pop_stack();
9b69512014-05-01Henrik Grubbström (Grubba)  } } /*! @endclass BlockCipher */
62a8ee2014-06-14Henrik Grubbström (Grubba) #define BLOCKCIPHER_CIPHER_INHERIT (BUFFEREDCIPHER_CIPHER_INHERIT + \
2194f92018-11-04Marcus Comstedt  Nettle_BlockCipher_BufferedCipher_inh_num)
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @class BlockCipher16 *! *! This is the @[BlockCipher] class extended with algorithms *! that require a block size of @expr{16@} bytes. *! *! @seealso *! @[Cipher], @[BlockCipher], @[BufferedCipher], @[GCM] */ PIKECLASS BlockCipher16 { /* NOTE: MUST be first in the class to simplify access to symbols * in Cipher! */ /*! @decl inherit BlockCipher */
2194f92018-11-04Marcus Comstedt  INHERIT BlockCipher;
9b69512014-05-01Henrik Grubbström (Grubba) 
7901d22014-05-07Tobias S. Josefowitz #ifdef HAVE_NETTLE_GCM_H PIKEVAR object(Nettle_AEAD) GCM; #endif
8a91cb2016-04-14Henrik Grubbström (Grubba)  /*! @module KW *! *! The AES Key Wrapping algorithm from @rfc{3394@}.
2a31872016-04-14Henrik Grubbström (Grubba)  *! *! This algorithm is intended to be used to encode *! encryption keys which are a multiple of 8 bytes *! and at least 16 bytes long. *! *! @note *! This mode uses the @[AEAD] APIs, but it does NOT *! have support for authenticated data.
8a91cb2016-04-14Henrik Grubbström (Grubba)  */ PIKEVAR object(Nettle_BufferedCipher) KW; PIKECLASS _KW program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; {
896f2a2016-04-15Henrik Grubbström (Grubba)  /*! @decl inherit __builtin.Nettle.AE
8a91cb2016-04-14Henrik Grubbström (Grubba)  */
896f2a2016-04-15Henrik Grubbström (Grubba)  INHERIT "__builtin.Nettle.AE";
8a91cb2016-04-14Henrik Grubbström (Grubba) 
2a31872016-04-14Henrik Grubbström (Grubba)  /*! @decl string(8bit) name() *! Returns the name of the base cipher with @expr{".CCM"@} appended. */
8a91cb2016-04-14Henrik Grubbström (Grubba)  PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
2a31872016-04-14Henrik Grubbström (Grubba)  apply_external(1, f_Nettle_Cipher_name_fun_num, args); push_static_text(".KW");
8a91cb2016-04-14Henrik Grubbström (Grubba)  f_add(2); }
2a31872016-04-14Henrik Grubbström (Grubba)  PIKEFUN int(8..8) digest_size()
8a91cb2016-04-14Henrik Grubbström (Grubba)  {
2a31872016-04-14Henrik Grubbström (Grubba)  push_int(8); } PIKEFUN int(8..8) block_size() { push_int(8);
8a91cb2016-04-14Henrik Grubbström (Grubba)  } PIKEFUN int(1..) key_size() {
2a31872016-04-14Henrik Grubbström (Grubba)  apply_external(1, f_Nettle_Cipher_key_size_fun_num, args);
8a91cb2016-04-14Henrik Grubbström (Grubba)  }
2a31872016-04-14Henrik Grubbström (Grubba)  PIKEFUN int(8..8) iv_size()
8a91cb2016-04-14Henrik Grubbström (Grubba)  {
2a31872016-04-14Henrik Grubbström (Grubba)  push_int(8); } /*! @decl constant DEFAULT_IV *! *! This is the default initialization vector specified *! by @rfc{3394:2.2.3.1@}. */ EXTRA { add_string_constant("DEFAULT_IV", "\246\246\246\246\246\246\246\246", 0);
8a91cb2016-04-14Henrik Grubbström (Grubba)  } /*! @class State */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { DOCSTART() @decl inherit Cipher::State DOCEND() EXTRA { /* Perform an inherit of the State class (if any) that our parent
2fe8e02017-08-04Henrik Grubbström (Grubba)  * may contain via its inherit of __builtin.Nettle.AE.
8a91cb2016-04-14Henrik Grubbström (Grubba)  */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
8a91cb2016-04-14Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state; CVAR struct pike_string *iv; /* NB: Not finished. */ CVAR INT32 mode; EXIT gc_trivial; {
40338f2017-07-10Martin Nilsson  if(THIS->iv)
8a91cb2016-04-14Henrik Grubbström (Grubba)  free_string(THIS->iv); } /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; {
2194f92018-11-04Marcus Comstedt  apply_external(2, Nettle_BlockCipher_BufferedCipher_inh_offset +
8a91cb2016-04-14Henrik Grubbström (Grubba)  Nettle_Cipher_State_program_fun_num, 0); } /*! @decl void create() *! *! Initialize the KW state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module. */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; unsigned block_size; int f;
2a31872016-04-14Henrik Grubbström (Grubba)  apply_current(f_Nettle_BlockCipher16_cq__KW_State_substate_factory_fun_num,
8a91cb2016-04-14Henrik Grubbström (Grubba)  0); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); } apply(o, "block_size", 0); if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if (block_size != AES_BLOCK_SIZE) Pike_error("Bad block size %d.\n", block_size); if(!THIS->iv) {
2a31872016-04-14Henrik Grubbström (Grubba)  THIS->iv = begin_shared_string(8*2);
8a91cb2016-04-14Henrik Grubbström (Grubba)  THIS->iv->flags |= STRING_CLEAR_ON_EXIT; } /* Initialize the iv with the default from RFC 3394 2.2.3.1. */
2a31872016-04-14Henrik Grubbström (Grubba)  memset(STR0(THIS->iv), 0xa6, 8*2);
8a91cb2016-04-14Henrik Grubbström (Grubba)  if (THIS->object) free_object(THIS->object); add_ref(THIS->object = o); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. * Check if the context and crypt function are valid. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits); } else { THIS->crypt_state = NULL;
1f87562018-01-01Martin Nilsson  } pop_n_elems(2);
8a91cb2016-04-14Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"KW(x)"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; { push_static_text("KW("); apply(THIS->object, "name", 0); push_static_text(")"); f_add(3); }
2a31872016-04-14Henrik Grubbström (Grubba)  /*! @decl int(8..8) block_size() *! Returns the block size for this AEAD mode.
8a91cb2016-04-14Henrik Grubbström (Grubba)  */
2a31872016-04-14Henrik Grubbström (Grubba)  PIKEFUN int(8..8) block_size()
8a91cb2016-04-14Henrik Grubbström (Grubba)  optflags OPT_TRY_OPTIMIZE; { RETURN 8; } /*! @decl int(1..) key_size() *! Returns the key size of the encapsulated cipher. */ PIKEFUN int(1..) key_size() optflags OPT_EXTERNAL_DEPEND; { apply(THIS->object, "key_size", args); }
2a31872016-04-14Henrik Grubbström (Grubba)  /*! @decl int(8..8) iv_size()
8a91cb2016-04-14Henrik Grubbström (Grubba)  *! Returns the size for the initialization vector */ PIKEFUN int(1..) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN 8; } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { THIS->mode = 0; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_encrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! 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(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; { THIS->mode = 1; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_decrypt_key", args); pop_stack(); push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released.
2a31872016-04-14Henrik Grubbström (Grubba)  *! *! The default iv if this function hasn't been called is *! @expr{"\246\246\246\246\246\246\246\246"@} (cf @rfc{3394:2.2.3.1@}. *! *! @seealso *! @[digest()], @[DEFAULT_IV]
8a91cb2016-04-14Henrik Grubbström (Grubba)  */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { assert(THIS->iv); iv->flags |= STRING_CLEAR_ON_EXIT; NO_WIDE_STRING(iv); if(iv->len != 8)
2a31872016-04-14Henrik Grubbström (Grubba)  Pike_error("Invalid initialization vector size.\n");
8a91cb2016-04-14Henrik Grubbström (Grubba)  memcpy(STR0(THIS->iv), STR0(iv), 8);
2a31872016-04-14Henrik Grubbström (Grubba)  memcpy(STR0(THIS->iv) + 8, STR0(iv), 8);
8a91cb2016-04-14Henrik Grubbström (Grubba)  RETURN this_object(); } /*! @decl string(0..255) crypt(string(0..255) data) *! *! Encrypt/decrypt @[data] and return the result. @[data] must *! be an integral number of blocks. It must also be at least *! two blocks long. *! *! 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(0..255) data) { struct pike_string *result; ONERROR uwp; pike_nettle_crypt_func func = pike_crypt_func; void *ctx = THIS->object; struct pike_string *iv = THIS->iv; p_wchar0 buf[AES_BLOCK_SIZE]; union { INT64 i64; p_wchar0 bin[8]; } t; NO_WIDE_STRING(data); if(data->len & 0x07) Pike_error("Data length not multiple of block size.\n"); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); }
2a31872016-04-14Henrik Grubbström (Grubba)  /* Decryption. */ if (data->len < 16) Pike_error("Data too short. At lease 16 bytes required.\n");
8a91cb2016-04-14Henrik Grubbström (Grubba) 
2a31872016-04-14Henrik Grubbström (Grubba)  result = begin_shared_string(data->len);
8a91cb2016-04-14Henrik Grubbström (Grubba)  SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } if(THIS->mode) { /* Decryption. */ ptrdiff_t i; int j, k;
2a31872016-04-14Henrik Grubbström (Grubba)  memcpy(buf, THIS->iv->str, 8); memcpy(result->str, data->str, data->len); t.i64 = (data->len / 8) * 6;
8a91cb2016-04-14Henrik Grubbström (Grubba)  for (j = 0; j < 6; j++) {
2a31872016-04-14Henrik Grubbström (Grubba)  for (i = data->len; i > 0; ) {
8a91cb2016-04-14Henrik Grubbström (Grubba)  i -= 8; for (k = 0; k < 8; k++) { #if PIKE_BYTEORDER == 4321 buf[k] ^= t.bin[k]; #else buf[k] ^= t.bin[7-k]; #endif } t.i64--; memcpy(buf + 8, result->str + i, 8); func(ctx, 16, buf, buf); memcpy(result->str + i, buf + 8, 8); } }
2a31872016-04-14Henrik Grubbström (Grubba)  memcpy(THIS->iv->str + 8, buf, 8);
8a91cb2016-04-14Henrik Grubbström (Grubba)  } else { ptrdiff_t i; int j, k; /* Encryption RFC 3394 2.2.1. */ t.i64 = 0; memcpy(buf, THIS->iv->str, 8);
2a31872016-04-14Henrik Grubbström (Grubba)  memcpy(result->str, data->str, data->len);
8a91cb2016-04-14Henrik Grubbström (Grubba)  for (j = 0; j < 6; j++) { for (i = 0; i < data->len; i+= 8) {
2a31872016-04-14Henrik Grubbström (Grubba)  memcpy(buf + 8, result->str + i, 8);
8a91cb2016-04-14Henrik Grubbström (Grubba)  func(ctx, 16, buf, buf); t.i64++; for (k = 0; k < 8; k++) { #if PIKE_BYTEORDER == 4321 buf[k] ^= t.bin[k]; #else buf[k] ^= t.bin[7-k]; #endif }
2a31872016-04-14Henrik Grubbström (Grubba)  memcpy(result->str + i, buf + 8, 8);
8a91cb2016-04-14Henrik Grubbström (Grubba)  } }
2a31872016-04-14Henrik Grubbström (Grubba)  memcpy(THIS->iv->str + 8, buf, 8);
8a91cb2016-04-14Henrik Grubbström (Grubba)  } pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); }
2a31872016-04-14Henrik Grubbström (Grubba)  /*! @decl string(8bit) digest() *! *! Returns the data integrity value. *! *! When decoding this value should be compared to *! the original IV used when encoding. *! *! When encoding the convention is to prepend this *! value to the encoded data returned by @[crypt()]. *! *! @note *! The above convention is the reverse of the convention for *! most @[AEAD]s (where the digest typically comes last). *! *! @seealso *! @[set_iv()], @[DEFAULT_IV] */ PIKEFUN string(8bit) digest() { push_string(make_shared_binary_string(THIS->iv->str + 8, 8)); }
8a91cb2016-04-14Henrik Grubbström (Grubba)  } /*! @endclass State */ } /*! @endmodule */
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @module CCM *! *! Implementation of the Counter with Cipher Block Chaining
1d65ab2014-06-08Henrik Grubbström (Grubba)  *! Message Authentication Code mode (CCM). *! *! Works as a wrapper for the cipher implemented by overloading *! the parent class (@[BlockCipher16]).
9b69512014-05-01Henrik Grubbström (Grubba)  *! *! This is a so-called authenticated encryption with associated data *! (AEAD) algorithm, and in addition to encryption also provides *! message digests. *! *! The operation of CCM is specified in *! NIST Special Publication 800-38C. *! *! @note *! This mode of operation is not suited for streaming operation, *! as the sizes of the associated data and payload data need to *! be known for the CBC-MAC operation to start. Currently this *! means that the associated data and payload data are buffered *! until @[State()->digest()] is called. *! *! @seealso *! @[CCM8], @[CBC], @[GCM], @[CTR] */ PIKEVAR object(Nettle_AEAD) CCM; PIKECLASS _CCM
1d65ab2014-06-08Henrik Grubbström (Grubba)  program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
9b69512014-05-01Henrik Grubbström (Grubba)  { /*! @decl inherit __builtin.Nettle.AEAD */ INHERIT "__builtin.Nettle.AEAD"; /*! @decl inherit BlockCipher::CTR */ EXTRA { /* Perform an inherit if the _CTR class that our parent contains * via its inherit of BlockCipher. */
f35ab02017-08-02Martin Nilsson  lexical_inherit(1, MK_STRING("_CTR"), 0, REPORT_ERROR);
9b69512014-05-01Henrik Grubbström (Grubba)  }
9004d12014-05-11Henrik Grubbström (Grubba)  /*! @decl string(8bit) name() *! Returns the name of the base cipher with @expr{".CCM"@} appended.
9b69512014-05-01Henrik Grubbström (Grubba)  */
9004d12014-05-11Henrik Grubbström (Grubba)  PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE;
9b69512014-05-01Henrik Grubbström (Grubba)  {
9004d12014-05-11Henrik Grubbström (Grubba)  apply_external(1, f_Nettle_Cipher_name_fun_num, args);
5e9fc02015-08-18Per Hedbor  push_static_text(".CCM");
9004d12014-05-11Henrik Grubbström (Grubba)  f_add(2);
9b69512014-05-01Henrik Grubbström (Grubba)  } /*! @decl int(4..16) digest_size() *! Default digest size. *! *! @returns *! Returns @expr{16@}, but overloading via inherit is supported, *! and may return any even number in the range @expr{[4..16]@}. *! *! @note *! Note that the digest length is folded into the digest, so *! it doesn't simply imply a truncation. */ PIKEFUN int(4..16) digest_size() { push_int(16); }
9004d12014-05-11Henrik Grubbström (Grubba)  PIKEFUN int(1..) block_size() { apply_external(1, f_Nettle_Cipher_block_size_fun_num, args); } PIKEFUN int(1..) key_size() { apply_external(1, f_Nettle_Cipher_key_size_fun_num, args); }
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) iv_size()
9004d12014-05-11Henrik Grubbström (Grubba)  { apply_external(1, f_Nettle_Cipher_block_size_fun_num, args); }
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @class State */ PIKECLASS State
1d65ab2014-06-08Henrik Grubbström (Grubba)  program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
9b69512014-05-01Henrik Grubbström (Grubba)  { /*! @decl inherit CTR::State */ static int ccm_state_inh_ctr_state_create_fun_num = -1; static int ccm_state_inh_ctr_state_crypt_fun_num = -1; static int ccm_state_inh_ctr_state_set_encrypt_key_fun_num = -1; static int ccm_state_inh_ctr_state_set_decrypt_key_fun_num = -1; EXTRA { /* Perform an inherit of the _CTR.State class that our parent * contains via its inherit of _CTR. */
f35ab02017-08-02Martin Nilsson  lexical_inherit(1, MK_STRING("State"), 0, REPORT_ERROR);
9b69512014-05-01Henrik Grubbström (Grubba)  /* We want to call some of our inherited functions recursively... */ ccm_state_inh_ctr_state_create_fun_num = really_low_reference_inherited_identifier(NULL, 1, f_Nettle_BlockCipher_cq__CTR_State_create_fun_num); ccm_state_inh_ctr_state_crypt_fun_num = really_low_reference_inherited_identifier(NULL, 1, f_Nettle_BlockCipher_cq__CTR_State_crypt_fun_num); ccm_state_inh_ctr_state_set_encrypt_key_fun_num = really_low_reference_inherited_identifier(NULL, 1, f_Nettle_BlockCipher_cq__CTR_State_set_encrypt_key_fun_num); ccm_state_inh_ctr_state_set_decrypt_key_fun_num = really_low_reference_inherited_identifier(NULL, 1, f_Nettle_BlockCipher_cq__CTR_State_set_decrypt_key_fun_num); } CVAR int decrypt_mode; PIKEVAR string(8bit) mac_mask flags ID_PRIVATE; PIKEVAR string(8bit) nonce flags ID_PROTECTED; CVAR struct string_builder abuf; CVAR struct string_builder pbuf; CVAR struct Nettle_BlockCipher_cq__CTR_State_struct *ctr; INIT { init_string_builder(&THIS->abuf, 0); init_string_builder(&THIS->pbuf, 0); ASSIGN_CURRENT_STORAGE(THIS->ctr, struct Nettle_BlockCipher_cq__CTR_State_struct, 1, Nettle_BlockCipher_cq__CTR_State_program); } EXIT {
40338f2017-07-10Martin Nilsson  free_string_builder(&THIS->abuf);
9b69512014-05-01Henrik Grubbström (Grubba)  free_string_builder(&THIS->pbuf); } /*! @decl void create() */ PIKEFUN void create() flags ID_PROTECTED; { apply_current(ccm_state_inh_ctr_state_create_fun_num, args); pop_stack(); if (THIS->ctr->block_size != 16) { Pike_error("Invalid block cipher for CCM: %d.\n", THIS->ctr->block_size); } reset_string_builder(&THIS->abuf); reset_string_builder(&THIS->pbuf); if (THIS->nonce) free_string(THIS->nonce); THIS->nonce = NULL; } PIKEFUN string(8bit) name() {
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->ctr->object, "name", args);
5e9fc02015-08-18Per Hedbor  push_static_text(".CCM");
9b69512014-05-01Henrik Grubbström (Grubba)  f_add(2); } PIKEFUN object(Nettle_AEAD_State) set_encrypt_key(string(8bit) key, int|void flags) { reset_string_builder(&THIS->abuf); reset_string_builder(&THIS->pbuf); THIS->decrypt_mode = 0; apply_current(ccm_state_inh_ctr_state_set_encrypt_key_fun_num, args); } PIKEFUN object(Nettle_AEAD_State) set_decrypt_key(string(8bit) key, int|void flags) { reset_string_builder(&THIS->abuf); reset_string_builder(&THIS->pbuf); THIS->decrypt_mode = 1; apply_current(ccm_state_inh_ctr_state_set_decrypt_key_fun_num, args); } PIKEFUN object(Nettle_AEAD_State) set_iv(string(8bit) iv) { int iv_len = iv->len; uint8_t *ctr_iv; iv->flags |= STRING_CLEAR_ON_EXIT; NO_WIDE_STRING(iv); reset_string_builder(&THIS->abuf); reset_string_builder(&THIS->pbuf); if (iv_len < 7) { Pike_error("Too short nonce for CCM. Must be at least 7 bytes.\n"); } if (THIS->nonce) { free_string(THIS->nonce); THIS->nonce = NULL; } if (iv_len > 13) { THIS->nonce = string_slice(iv, 0, 12); iv_len = 13; } else { add_ref(THIS->nonce = iv); }
1a31102014-05-13Henrik Grubbström (Grubba)  ctr_iv = STR0(THIS->ctr->iv);
9b69512014-05-01Henrik Grubbström (Grubba)  *(ctr_iv++) = 14 - iv_len;
59fc9e2014-09-03Martin Nilsson  memcpy(ctr_iv, STR0(iv), iv_len);
21b12a2014-09-03Martin Nilsson  memset(ctr_iv + iv_len, 0, 15 - iv_len);
9b69512014-05-01Henrik Grubbström (Grubba)  RETURN this_object(); } PIKEFUN object(Nettle_AEAD_State) update(string(8bit) public_data) { if (!public_data->len) return; NO_WIDE_STRING(public_data); string_builder_shared_strcat(&THIS->abuf, public_data); RETURN this_object(); }
391ac52018-08-05Martin Nilsson  static void blockcipher16_ccm_init_mac_mask()
9b69512014-05-01Henrik Grubbström (Grubba)  { struct pike_string *mac_mask; if (!THIS->nonce) { /* NB: Default to nonce of 13 NULs. */ add_ref(THIS->nonce = nul13_string);
4d96662017-10-31Henrik Grubbström (Grubba)  memcpy(STR0(THIS->ctr->iv), "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16);
9b69512014-05-01Henrik Grubbström (Grubba)  } /* Save the first block from the CTR to encrypt the MAC. */ ref_push_string(nul16_string); apply_current(ccm_state_inh_ctr_state_crypt_fun_num, 1);
391ac52018-08-05Martin Nilsson  get_all_args(NULL, 1, "%n", &mac_mask);
9b69512014-05-01Henrik Grubbström (Grubba)  NO_WIDE_STRING(mac_mask); if (mac_mask->len != 16) { Pike_error("Bad string length %ld returned from crypt()\n",
77af4f2015-10-14Martin Nilsson  (long)mac_mask->len);
9b69512014-05-01Henrik Grubbström (Grubba)  } if (THIS->mac_mask) free_string(THIS->mac_mask); add_ref(THIS->mac_mask = mac_mask); pop_stack(); } PIKEFUN string(8bit) crypt(string(8bit) data) { if (!data->len) { return; } NO_WIDE_STRING(data); if (!THIS->pbuf.s->len) {
391ac52018-08-05Martin Nilsson  blockcipher16_ccm_init_mac_mask();
9b69512014-05-01Henrik Grubbström (Grubba)  } if (!THIS->decrypt_mode) { string_builder_shared_strcat(&THIS->pbuf, data); } apply_current(ccm_state_inh_ctr_state_crypt_fun_num, args); if (THIS->decrypt_mode) {
391ac52018-08-05Martin Nilsson  get_all_args(NULL, 1, "%n", &data);
9b69512014-05-01Henrik Grubbström (Grubba)  NO_WIDE_STRING(data); string_builder_shared_strcat(&THIS->pbuf, data); } } /*! @decl int(4..16) digest_size() *! *! Default digest size. *! *! This function is used by @[digest()] to determine the digest *! size if no argument was given. *! *! @returns *! The default implementation returns the result from calling *! @[global::digest_size()], but overloading via inherit is supported, *! and may return any even number in the range @expr{[4..16]@}. *! *! @note *! Note that the digest length is folded into the digest, so *! it doesn't simply imply a truncation. *! *! @seealso *! @[digest()], @[CCM::digest_size()] */ PIKEFUN int(4..16) digest_size() { apply_external(1, f_Nettle_BlockCipher16_cq__CCM_digest_size_fun_num, args); }
0473d52014-05-11Henrik Grubbström (Grubba)  static void pike_low_ccm_digest(struct pike_string *res, struct pike_string *nonce, struct pike_string *mac_mask, struct pike_string *astr, struct pike_string *pstr,
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func,
0473d52014-05-11Henrik Grubbström (Grubba)  void *ctx)
9b69512014-05-01Henrik Grubbström (Grubba)  {
0473d52014-05-11Henrik Grubbström (Grubba)  uint8_t buf[2][16]; size_t bytes = res->len; size_t psize = pstr->len; int i;
9b69512014-05-01Henrik Grubbström (Grubba)  int flags; int bufno = 0; uint8_t *ptr;
0473d52014-05-11Henrik Grubbström (Grubba)  flags = ((bytes-2)<<2) | (14 - nonce->len); if (astr->len) {
9b69512014-05-01Henrik Grubbström (Grubba)  // Set the a-bit. flags |= 0x40; }
0473d52014-05-11Henrik Grubbström (Grubba)  psize = pstr->len;
9b69512014-05-01Henrik Grubbström (Grubba)  /* NB: The nonce has a minimum size of 7 bytes. * Thus we need at most 8 bytes for the psize. */ /* |flags|nonce|psize| */ ptr = buf[0] + 8; for (i = 8; i--; psize >>= 8) {
1c37ed2014-05-09Henrik Grubbström (Grubba)  ptr[i] = psize & 0xff;
9b69512014-05-01Henrik Grubbström (Grubba)  } buf[0][0] = flags;
59fc9e2014-09-03Martin Nilsson  memcpy(buf[0]+1, STR0(nonce), nonce->len);
9b69512014-05-01Henrik Grubbström (Grubba)  func(ctx, 16, buf[1], buf[0]); bufno = 1;
0473d52014-05-11Henrik Grubbström (Grubba)  if (astr->len) { size_t asize = astr->len; ptr = STR0(astr);
9b69512014-05-01Henrik Grubbström (Grubba)  if (asize < 0xff00) { buf[1][0] ^= (asize >> 8) & 0xff; buf[1][1] ^= asize & 0xff; if (asize < 14) { memxor(buf[1]+2, ptr, asize); asize = 0; } else { memxor(buf[1], ptr, 14); ptr += 14; asize -= 14; }
59d3d42014-11-05Henrik Grubbström (Grubba) #if (SIZEOF_CHARP > 4) } else if (asize > 0xffffffffUL) {
9b69512014-05-01Henrik Grubbström (Grubba)  buf[1][0] ^= 0xff; buf[1][1] ^= 0xff; buf[1][2] ^= (asize >> 56) & 0xff; buf[1][3] ^= (asize >> 48) & 0xff; buf[1][4] ^= (asize >> 40) & 0xff; buf[1][5] ^= (asize >> 32) & 0xff; buf[1][6] ^= (asize >> 24) & 0xff; buf[1][7] ^= (asize >> 16) & 0xff; buf[1][8] ^= (asize >> 8) & 0xff; buf[1][9] ^= asize & 0xff; memxor(buf[1]+10, ptr, 6); ptr += 6; asize -= 6;
59d3d42014-11-05Henrik Grubbström (Grubba) #endif } else { buf[1][0] ^= 0xff; buf[1][1] ^= 0xfe; buf[1][2] ^= (asize >> 24) & 0xff; buf[1][3] ^= (asize >> 16) & 0xff; buf[1][4] ^= (asize >> 8) & 0xff; buf[1][5] ^= asize & 0xff; memxor(buf[1]+6, ptr, 10); ptr += 10; asize -= 10;
9b69512014-05-01Henrik Grubbström (Grubba)  } func(ctx, 16, buf[0], buf[1]); bufno = 0; for (;asize >= 16; asize -= 16, ptr += 16) { memxor(buf[bufno], ptr, 16); func(ctx, 16, buf[!bufno], buf[bufno]); bufno = !bufno; } if (asize) { memxor(buf[bufno], ptr, asize); func(ctx, 16, buf[!bufno], buf[bufno]); bufno = !bufno; } }
0473d52014-05-11Henrik Grubbström (Grubba)  ptr = STR0(pstr); psize = pstr->len;
9b69512014-05-01Henrik Grubbström (Grubba)  for (; psize >= 16; psize -= 16, ptr += 16) { memxor(buf[bufno], ptr, 16); func(ctx, 16, buf[!bufno], buf[bufno]); bufno = !bufno;
23225e2014-04-30Henrik Grubbström (Grubba)  }
9b69512014-05-01Henrik Grubbström (Grubba)  if (psize) { memxor(buf[bufno], ptr, psize); func(ctx, 16, buf[!bufno], buf[bufno]); bufno = !bufno;
23225e2014-04-30Henrik Grubbström (Grubba)  }
0473d52014-05-11Henrik Grubbström (Grubba)  memxor3(STR0(res), buf[bufno], STR0(mac_mask), bytes); }
9b69512014-05-01Henrik Grubbström (Grubba) 
0473d52014-05-11Henrik Grubbström (Grubba)  /*! @decl string(8bit) digest(int(4..16)|void bytes) *! *! Returns the CBC-MAC digest of the specified size. *! *! @param bytes *! Size in bytes for the desired digest. Any even number in *! the range @expr{[4..16]@}. If not specified the value from *! calling @[digest_size()] will be used. *! *! @note *! Note that the digest length is folded into the digest, so *! it doesn't simply imply a truncation. *! *! @seealso *! @[digest_size()], @[global::digest_size()] */ PIKEFUN string(8bit) digest(int(4..16)|void bytes_p) { int bytes = 0;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
0473d52014-05-11Henrik Grubbström (Grubba)  void *ctx = THIS->ctr->object; struct pike_string *res; struct pike_string *nonce = THIS->nonce; struct pike_string *mac_mask = THIS->mac_mask; struct pike_string *astr = THIS->abuf.s; struct pike_string *pstr = THIS->pbuf.s; if (bytes_p) { bytes = bytes_p->u.integer; if (bytes & 1) { bytes++; } } if (!bytes) { apply_current(f_Nettle_BlockCipher16_cq__CCM_State_digest_size_fun_num, 0);
391ac52018-08-05Martin Nilsson  get_all_args(NULL, 1, "%d", &bytes);
0473d52014-05-11Henrik Grubbström (Grubba)  } if (bytes < 4) { bytes = 4; } else if (bytes > 16) { bytes = 16; } res = begin_shared_string(bytes); if (!pstr->len) { // Unlikely, but make sure that it is initialized.
391ac52018-08-05Martin Nilsson  blockcipher16_ccm_init_mac_mask();
0473d52014-05-11Henrik Grubbström (Grubba)  } if (THIS->ctr->crypt_state && THIS->ctr->crypt_state->crypt) { func = THIS->ctr->crypt_state->crypt; ctx = THIS->ctr->crypt_state->ctx; } if (((THIS->abuf.s->len + THIS->pbuf.s->len) >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { /* NB: This is a rather expensive MAC, as it is based * on encrypting with CBC. */ /* Protect stuff in the object from being freed * by a different thread while we use them. */ add_ref(nonce); add_ref(mac_mask); add_ref(astr); add_ref(pstr); THREADS_ALLOW(); pike_low_ccm_digest(res, nonce, mac_mask, astr, pstr, func, ctx); THREADS_DISALLOW(); free_string(pstr); free_string(astr); free_string(mac_mask); free_string(nonce); } else { pike_low_ccm_digest(res, nonce, mac_mask, astr, pstr, func, ctx); } reset_string_builder(&THIS->pbuf); reset_string_builder(&THIS->abuf);
9b69512014-05-01Henrik Grubbström (Grubba)  push_string(end_shared_string(res));
23225e2014-04-30Henrik Grubbström (Grubba)  } } /*! @endclass State */ }
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @endmodule CCM */
23225e2014-04-30Henrik Grubbström (Grubba) 
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @module CCM8 *! *! Special case of @[CCM] where the default digest size *! has been truncated to @expr{8@} bytes. *! *! @seealso *! @[CCM], @[CBC], @[GCM], @[CTR]
23225e2014-04-30Henrik Grubbström (Grubba)  */
9b69512014-05-01Henrik Grubbström (Grubba)  PIKEVAR object(Nettle_AEAD) CCM8;
23225e2014-04-30Henrik Grubbström (Grubba) 
9b69512014-05-01Henrik Grubbström (Grubba)  PIKECLASS _CCM8
1d65ab2014-06-08Henrik Grubbström (Grubba)  program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT;
23225e2014-04-30Henrik Grubbström (Grubba)  {
9de5782014-08-22Henrik Grubbström (Grubba)  /*! @decl inherit CCM
9b69512014-05-01Henrik Grubbström (Grubba)  */ EXTRA {
27b78a2014-10-06Henrik Grubbström (Grubba)  /* Perform an inherit of the _CCM class that our parent contains.
9b69512014-05-01Henrik Grubbström (Grubba)  */
27b78a2014-10-06Henrik Grubbström (Grubba)  /* FIXME: */
9b69512014-05-01Henrik Grubbström (Grubba)  low_inherit(Nettle_BlockCipher16_cq__CCM_program, 0, Nettle_BlockCipher16_cq__CCM_program_fun_num, 1 + 42, 0, NULL);
23225e2014-04-30Henrik Grubbström (Grubba)  }
3747282014-04-30Henrik Grubbström (Grubba) 
9004d12014-05-11Henrik Grubbström (Grubba)  /*! @decl string(8bit) name() *! Returns the name of the base cipher with @expr{".CCM8"@} appended.
9b69512014-05-01Henrik Grubbström (Grubba)  */ PIKEFUN string(7bit) name() {
9004d12014-05-11Henrik Grubbström (Grubba)  apply_external(1, f_Nettle_Cipher_name_fun_num, args);
5e9fc02015-08-18Per Hedbor  push_static_text(".CCM8");
9004d12014-05-11Henrik Grubbström (Grubba)  f_add(2);
9b69512014-05-01Henrik Grubbström (Grubba)  }
3747282014-04-30Henrik Grubbström (Grubba) 
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @decl int(4..16) digest_size() *! Default digest size. *! *! @returns *! Returns @expr{8@}, but overloading via inherit is supported, *! and may return any even number in the range @expr{[4..16]@}. */ PIKEFUN int(4..16) digest_size() { push_int(8); } } /*! @endmodule CCM8
ef84602014-04-26Henrik Grubbström (Grubba)  */
9ce28d2014-06-09Henrik Grubbström (Grubba) #ifdef HAVE_NETTLE_EAX_H #include <nettle/eax.h> /*! @module EAX *! *! Implementation of the EAX mode. *! *! Works as a wrapper for the cipher implemented by overloading *! the parent class (@[BlockCipher16]). *! *! This is a so-called authenticated encryption with associated data *! (AEAD) algorithm, and in addition to encryption also provides *! message digests. *! *! @note *! This mode of operation was specified as a reaction to the *! limitiations of the @[BlockCipher16.CCM] mode. *! *! @note *! Note that this module is not available in all versions of Nettle. *! *! @seealso *! @[CBC], @[CTR], @[BlockCipher16.CCM], @[BlockCipher16.GCM] */
51f0802017-06-04Henrik Grubbström (Grubba)  PIKEVAR object(Nettle_AEAD) EAX /* NB: Solaris 11/x86 has a conflicting #define of EAX in <sys/regset.h>, * which gets included when __EXTENSIONS__ is defined. */ c_name EAX_object;
9ce28d2014-06-09Henrik Grubbström (Grubba)  PIKECLASS _EAX program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit __builtin.Nettle.AEAD */ INHERIT "__builtin.Nettle.AEAD"; /*! @decl string(8bit) name() *! Returns the name of the base cipher with @expr{".EAX"@} appended. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; { apply_external(1, f_Nettle_Cipher_name_fun_num, args);
5e9fc02015-08-18Per Hedbor  push_static_text(".EAX");
9ce28d2014-06-09Henrik Grubbström (Grubba)  f_add(2); } /*! @decl int(1..) digest_size() *! Default digest size. *! *! @returns *! Returns @[BlockCipher::block_size()], but overloading via *! inherit is supported, and may return any positive number *! @expr{<= BlockCipher::block_size()@}. */ PIKEFUN int(1..) digest_size() { apply_external(1, f_Nettle_Cipher_block_size_fun_num, args); } PIKEFUN int(1..) block_size() { apply_external(1, f_Nettle_Cipher_block_size_fun_num, args); } PIKEFUN int(1..) key_size() { apply_external(1, f_Nettle_Cipher_key_size_fun_num, args); } PIKEFUN int(1..) iv_size() { apply_external(1, f_Nettle_Cipher_block_size_fun_num, args); } /*! @class State */ PIKECLASS State
9e336b2014-06-19Henrik Grubbström (Grubba)  program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT|PROGRAM_CLEAR_STORAGE;
9ce28d2014-06-09Henrik Grubbström (Grubba)  { PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state; CVAR int block_size; CVAR int mode; CVAR struct eax_key eax_key; CVAR struct eax_ctx eax_ctx;
9e336b2014-06-19Henrik Grubbström (Grubba)  /*! @decl inherit AEAD::State
9ce28d2014-06-09Henrik Grubbström (Grubba)  */ EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the State class (if any) that our parent * may contain via its inherit of __builtin.Nettle.AEAD.
9ce28d2014-06-09Henrik Grubbström (Grubba)  */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
9ce28d2014-06-09Henrik Grubbström (Grubba)  } /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; { apply_external(2, Nettle_Cipher_State_program_fun_num, 0); } /*! @decl void create() */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; int block_size; int f; apply_current(f_Nettle_BlockCipher16_cq__EAX_State_substate_factory_fun_num, args); if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); } apply(o, "block_size", 0); if(TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); block_size = Pike_sp[-1].u.integer; if (block_size != EAX_BLOCK_SIZE) Pike_error("Bad block size for EAX: %d.\n", block_size); THIS->block_size = block_size; if (THIS->object) free_object(THIS->object); add_ref(THIS->object = o); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits); } else { THIS->crypt_state = NULL; }
1f87562018-01-01Martin Nilsson  THIS->mode = 0; pop_n_elems(2);
9ce28d2014-06-09Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"x.EAX"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(8bit) name() { apply(THIS->object, "name", args);
5e9fc02015-08-18Per Hedbor  push_static_text(".EAX");
9ce28d2014-06-09Henrik Grubbström (Grubba)  f_add(2); } /*! @decl int(16..16) block_size() *! Returns the block size of the encapsulated cipher, *! which is always @expr{16@} for EAX. */ PIKEFUN int(16..16) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN EAX_BLOCK_SIZE; } /*! @decl int(1..16) digest_size() *! *! Default digest size. *! *! This function is used by @[digest()] to determine the digest *! size if no argument was given. *! *! @returns *! The default implementation returns the result from calling *! @[EAX::digest_size()], but overloading via inherit is supported, *! and may return any even number in the range @expr{[1..16]@}. *! *! @seealso *! @[digest()], @[EAX::digest_size()] */ PIKEFUN int(1..16) digest_size() optflags OPT_TRY_OPTIMIZE; { apply_external(1, f_Nettle_BlockCipher16_cq__EAX_digest_size_fun_num, args); } /*! @decl int(16..16) iv_size() *! Returns the recommended size for the initialization vector *! (ie @expr{16@}). *! *! Other sizes are allowed, but will be compressed or expanded *! to this size using the encapsulated cipher. */ PIKEFUN int(16..16) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN EAX_IV_SIZE; } /*! @decl int(1..) key_size() *! Returns the key size of the encapsulated cipher. */ PIKEFUN int(1..) key_size() optflags OPT_EXTERNAL_DEPEND; { apply(THIS->object, "key_size", args); } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for encrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_decrypt_key()], @[set_iv()] */ PIKEFUN object(Nettle_AEAD_State) set_encrypt_key(string(8bit) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9ce28d2014-06-09Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; apply(THIS->object, "set_encrypt_key", args); pop_stack(); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } eax_set_key(&THIS->eax_key, ctx, func); THIS->mode = 0; push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for decrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_encrypt_key()], @[set_iv()] */ PIKEFUN object(Nettle_AEAD_State) set_decrypt_key(string(8bit) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9ce28d2014-06-09Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; /* NOTE: EAX always uses the encryption function * of the underlying cipher! */ apply(THIS->object, "set_encrypt_key", args); pop_stack(); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } eax_set_key(&THIS->eax_key, ctx, func); THIS->mode = 1; push_object(this_object()); } PIKEFUN object(Nettle_AEAD_State) set_iv(string(8bit) iv) {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9ce28d2014-06-09Henrik Grubbström (Grubba)  void *ctx = THIS->object; int iv_len = iv->len; uint8_t *ctr_iv; iv->flags |= STRING_CLEAR_ON_EXIT; NO_WIDE_STRING(iv); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } eax_set_nonce(&THIS->eax_ctx, &THIS->eax_key, ctx, func, iv->len, STR0(iv)); RETURN this_object(); } PIKEFUN object(Nettle_AEAD_State) update(string(8bit) public_data) {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9ce28d2014-06-09Henrik Grubbström (Grubba)  void *ctx = THIS->object; if (!public_data->len) return; NO_WIDE_STRING(public_data); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } eax_update(&THIS->eax_ctx, &THIS->eax_key, ctx, func, public_data->len, STR0(public_data)); RETURN this_object(); } PIKEFUN string(8bit) crypt(string(8bit) data) {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9ce28d2014-06-09Henrik Grubbström (Grubba)  void *ctx = THIS->object; struct pike_string *res; if (!data->len) { return; } NO_WIDE_STRING(data); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } res = begin_shared_string(data->len); if (!THIS->mode) { eax_encrypt(&THIS->eax_ctx, &THIS->eax_key, ctx, func, data->len, STR0(res), STR0(data)); } else { eax_decrypt(&THIS->eax_ctx, &THIS->eax_key, ctx, func, data->len, STR0(res), STR0(data)); } push_string(end_shared_string(res)); } /*! @decl string(8bit) digest(int(1..16)|void bytes) *! *! Returns the OMAC digest of the specified size. *! *! @param bytes *! Size in bytes for the desired digest. Any number in the *! range @expr{[1..16]@}. If not specified the value from *! calling @[digest_size()] will be used. *! *! @seealso *! @[digest_size()], @[global::digest_size()] */ PIKEFUN string(8bit) digest(int(1..16)|void bytes_p) { int bytes = 0;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
9ce28d2014-06-09Henrik Grubbström (Grubba)  void *ctx = THIS->object; struct pike_string *res; if (bytes_p) { bytes = bytes_p->u.integer; if (bytes & 1) { bytes++; } } if (!bytes) { apply_current(f_Nettle_BlockCipher16_cq__EAX_State_digest_size_fun_num, 0);
391ac52018-08-05Martin Nilsson  get_all_args(NULL, 1, "%d", &bytes);
9ce28d2014-06-09Henrik Grubbström (Grubba)  } if (bytes < 1) { bytes = 1; } else if (bytes > EAX_DIGEST_SIZE) { bytes = EAX_DIGEST_SIZE; } res = begin_shared_string(bytes); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } eax_digest(&THIS->eax_ctx, &THIS->eax_key, ctx, func, bytes, STR0(res)); push_string(end_shared_string(res)); } } /*! @endclass State */ } /*! @endmodule EAX */ #endif /* HAVE_NETTLE_EAX_H */
ef84602014-04-26Henrik Grubbström (Grubba) #ifdef HAVE_NETTLE_GCM_H
7901d22014-05-07Tobias S. Josefowitz 
ef84602014-04-26Henrik Grubbström (Grubba) #include <nettle/gcm.h> /*! @module GCM *! Implementation of the Galois Counter Mode (GCM). *! *! Works as a wrapper for the cipher implemented by overloading
1d65ab2014-06-08Henrik Grubbström (Grubba)  *! the parent class (@[BlockCipher16]).
ef84602014-04-26Henrik Grubbström (Grubba)  *! *! This is a so-called authenticated encryption with associated data *! (AEAD) algorithm, which in addition to encryption also provides *! message digests. *! *! The operation of GCM is specified in *! NIST Special Publication 800-38D. *! *! Typically accessed as @expr{Crypto.AES.GCM@} or *! @expr{Crypto.Camellia.GCM@} *! *! @note *! Note that this module is not available in all versions of Nettle. *! *! @seealso *! @[CBC] */ PIKECLASS _GCM program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit __builtin.Nettle.AEAD */ INHERIT "__builtin.Nettle.AEAD"; /*! @decl string(0..255) name() *! Returns the name of the base cipher with @expr{".GCM"@} appended. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; { apply_external(1, f_Nettle_Cipher_name_fun_num, args);
5e9fc02015-08-18Per Hedbor  push_static_text(".GCM");
9004d12014-05-11Henrik Grubbström (Grubba)  f_add(2); } PIKEFUN int(1..) key_size() { apply_external(1, f_Nettle_Cipher_key_size_fun_num, args);
ef84602014-04-26Henrik Grubbström (Grubba)  } /*! @decl int(16..16) block_size() *! Returns the block size of the encapsulated cipher, *! which is always @expr{16@} for GCM. */ PIKEFUN int(16..16) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN GCM_BLOCK_SIZE; } /*! @decl int(16..16) digest_size() *! Returns the size of the generated digest, *! which is always @expr{16@} for GCM. */ PIKEFUN int(16..16) digest_size() optflags OPT_TRY_OPTIMIZE; { RETURN GCM_BLOCK_SIZE; } /*! @decl int(12..12) iv_size() *! Returns the recommended size for the initialization vector *! (ie @expr{12@}). *! *! Other sizes are allowed, but will be compressed or expanded *! to this size using the encapsulated cipher. */ PIKEFUN int(12..12) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN GCM_IV_SIZE; } /*! @class State *! *! The state for a GCM instance. */
1f87562018-01-01Martin Nilsson  PIKECLASS State
9e336b2014-06-19Henrik Grubbström (Grubba)  program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;
ef84602014-04-26Henrik Grubbström (Grubba)  { DOCSTART() @decl inherit AEAD::State DOCEND() EXTRA { /* Perform an inherit of the State class (if any) that our parent * may contain via its inherit of __builtin.Nettle.AEAD. */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
ef84602014-04-26Henrik Grubbström (Grubba)  } PIKEVAR object object flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN; CVAR struct Nettle_Cipher_State_struct *crypt_state; CVAR INT32 mode; CVAR INT32 dmode; CVAR struct gcm_key gcm_key; CVAR struct gcm_ctx gcm_ctx; /* dmode flags */ #define NO_ADATA 1 /* Disallow associated data. */ #define NO_CDATA 2 /* Disallow crypted data. */ INIT { THIS->mode = -1; }
2680122014-05-02Henrik Grubbström (Grubba)  /*! @decl Cipher::State substate_factory() *! *! Returns the @[Cipher::State] object that this object *! is to operate on. *! *! Defaults to creating the State for the cipher implemented *! in the parent module. */ PIKEFUN object(Nettle_Cipher_State) substate_factory() flags ID_PROTECTED; { apply_external(2, Nettle_Cipher_State_program_fun_num, 0); }
ef84602014-04-26Henrik Grubbström (Grubba)  /*! @decl void create() *!
2680122014-05-02Henrik Grubbström (Grubba)  *! Initialize the GCM state with the @[Cipher::State] object *! returned by @[substate_factory()]. This is usually *! the State for the cipher implemented in the parent module.
ef84602014-04-26Henrik Grubbström (Grubba)  */ PIKEFUN void create() flags ID_PROTECTED; { struct object *o; struct inherit *inh; int f;
2680122014-05-02Henrik Grubbström (Grubba)  apply_current(f_Nettle_BlockCipher16_cq__GCM_State_substate_factory_fun_num, 0);
ef84602014-04-26Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) != T_OBJECT) { Pike_error("Unsupported return value from Cipher::State().\n"); } o = Pike_sp[-1].u.object; if (!o->prog) { Pike_error("Cipher::State() returned destructed object.\n"); } f = find_identifier("crypt", o->prog); if (f < 0) { Pike_error("State object has no crypt() function.\n"); }
8c53732014-05-13Henrik Grubbström (Grubba)  apply(o, "block_size", 0);
ef84602014-04-26Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) != T_INT) Pike_error("block_size() didn't return an int.\n"); if (Pike_sp[-1].u.integer != GCM_BLOCK_SIZE) Pike_error("cipher has an invalid block size for GCM.\n"); if (THIS->object) free_object(THIS->object); add_ref(THIS->object = o); inh = INHERIT_FROM_INT(o->prog, f); if (inh->prog == Nettle_Cipher_State_program) { /* crypt() is from Nettle.Cipher.State. */ THIS->crypt_state = (struct Nettle_Cipher_State_struct *) get_inherit_storage(o, inh - o->prog->inherits);
9b69512014-05-01Henrik Grubbström (Grubba)  } else { THIS->crypt_state = NULL;
ef84602014-04-26Henrik Grubbström (Grubba)  }
1f87562018-01-01Martin Nilsson  THIS->mode = -1; pop_n_elems(2);
ef84602014-04-26Henrik Grubbström (Grubba)  } /*! @decl string(0..255) name() *! Returns the string @expr{"x.GCM"@} where x is the *! encapsulated algorithm. */ PIKEFUN string(0..255) name() optflags OPT_TRY_OPTIMIZE; {
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "name", 0);
5e9fc02015-08-18Per Hedbor  push_static_text(".GCM");
ef84602014-04-26Henrik Grubbström (Grubba)  f_add(2); } /*! @decl int(16..16) block_size() *! Returns the block size of the encapsulated cipher, *! which is always @expr{16@} for GCM. */ PIKEFUN int(16..16) block_size() optflags OPT_TRY_OPTIMIZE; { RETURN GCM_BLOCK_SIZE; } /*! @decl int(16..16) digest_size() *! Returns the size of the generated digest, *! which is always @expr{16@} for GCM. */ PIKEFUN int(16..16) digest_size() optflags OPT_TRY_OPTIMIZE; { RETURN GCM_BLOCK_SIZE; } /*! @decl int(12..12) iv_size() *! Returns the recommended size for the initialization vector *! (ie @expr{12@}). *! *! Other sizes are allowed, but will be compressed or expanded *! to this size using the encapsulated cipher. */ PIKEFUN int(12..12) iv_size() optflags OPT_TRY_OPTIMIZE; { RETURN GCM_IV_SIZE; }
8c53732014-05-13Henrik Grubbström (Grubba)  /*! @decl int(1..) key_size()
ef84602014-04-26Henrik Grubbström (Grubba)  *! Returns the key size of the encapsulated cipher. */
8c53732014-05-13Henrik Grubbström (Grubba)  PIKEFUN int(1..) key_size()
ef84602014-04-26Henrik Grubbström (Grubba)  optflags OPT_EXTERNAL_DEPEND; {
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "key_size", args);
ef84602014-04-26Henrik Grubbström (Grubba)  } /*! @decl this_program set_encrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for encrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_decrypt_key()], @[set_iv()] */ PIKEFUN object set_encrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
ef84602014-04-26Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT;
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_encrypt_key", args);
ef84602014-04-26Henrik Grubbström (Grubba)  pop_stack(); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } gcm_set_key(&THIS->gcm_key, ctx, func); THIS->mode = 0; push_object(this_object()); } /*! @decl this_program set_decrypt_key(string(0..255) key, int|void flags) *! *! Prepare the cipher and the wrapper for decrypting with the given *! @[key]. The @[key] memory will be cleared before released. *! *! @note *! Note that this operation does not by itself reset the *! context sufficiently to start a new message; @[set_iv()] *! needs to be called too. *! *! @seealso *! @[set_encrypt_key()], @[set_iv()] */ PIKEFUN object set_decrypt_key(string(0..255) key, int|void flags) optflags OPT_SIDE_EFFECT; {
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
ef84602014-04-26Henrik Grubbström (Grubba)  void *ctx = THIS->object; key->flags |= STRING_CLEAR_ON_EXIT; /* NOTE: GCM always uses the encryption function * of the underlying cipher! */
8c53732014-05-13Henrik Grubbström (Grubba)  apply(THIS->object, "set_encrypt_key", args);
ef84602014-04-26Henrik Grubbström (Grubba)  pop_stack(); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } gcm_set_key(&THIS->gcm_key, ctx, func); THIS->mode = 1; push_object(this_object()); } /*! @decl this_program set_iv(string(0..255) iv) *! *! Set the initialization vector to @[iv]. The @[iv] memory will be *! cleared before released. *! *! Also resets all state needed to start a new message. *! *! @note *! For @[iv]s of length other than @expr{12@}, an encryption or *! decryption key must have been set first. *! *! @seealso *! @[set_encrypt_key()], @[set_decrypt_key()]. */ PIKEFUN object set_iv(string(0..255) iv) optflags OPT_SIDE_EFFECT; { iv->flags |= STRING_CLEAR_ON_EXIT; NO_WIDE_STRING(iv); if ((THIS->mode < 0) && (iv->len != GCM_IV_SIZE)) Pike_error("The key must be set to use an iv of length other than %d.\n", GCM_IV_SIZE); gcm_set_iv(&THIS->gcm_ctx, &THIS->gcm_key, iv->len, STR0(iv)); THIS->dmode = 0; RETURN this_object(); } /*! @decl void update(string(0..255) public_data) *! *! Add @[public_data] to be authenticated. *! *! The length of @[public_data] MUST be a multiple of the *! block size (ie @expr{16@}) for all calls except the last. *! *! All calls of @[update()] need to be performed before *! any calls of @[crypt()]. */ PIKEFUN void update(string(0..255) data) {
0473d52014-05-11Henrik Grubbström (Grubba)  struct gcm_ctx *gcm_ctx = &THIS->gcm_ctx; struct gcm_key *gcm_key = &THIS->gcm_key;
ef84602014-04-26Henrik Grubbström (Grubba)  NO_WIDE_STRING(data); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } if (THIS->mode < 0) Pike_error("Key schedule not initialized.\n"); if (THIS->dmode & NO_ADATA) Pike_error("Public data not allowed now.\n");
0473d52014-05-11Henrik Grubbström (Grubba)  if (data->len >= HASH_THREADS_ALLOW_THRESHOLD) { THREADS_ALLOW(); gcm_update(gcm_ctx, gcm_key, data->len, STR0(data)); THREADS_DISALLOW(); } else { gcm_update(gcm_ctx, gcm_key, data->len, STR0(data)); }
ef84602014-04-26Henrik Grubbström (Grubba)  if (data->len & (GCM_BLOCK_SIZE - 1)) THIS->dmode |= NO_ADATA; } /*! @decl string(0..255) crypt(string(0..255) data) *! *! Encrypt/decrypt @[data] and return the result. @[data] must *! be an integral number of blocks. *! *! The length of @[data] MUST be a multiple of the block size *! (ie @expr{16@}) for all calls except the last. *! *! Neither the input or output data is not automatically memory *! scrubbed, unless @[String.secure] has been called on the data. *! *! @seealso *! @[update()], @[digest()] */ PIKEFUN string(0..255) crypt(string(0..255) data) { struct pike_string *result; ONERROR uwp;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
ef84602014-04-26Henrik Grubbström (Grubba)  void *ctx = THIS->object;
0473d52014-05-11Henrik Grubbström (Grubba)  struct gcm_ctx *gcm_ctx = &THIS->gcm_ctx; struct gcm_key *gcm_key = &THIS->gcm_key;
ef84602014-04-26Henrik Grubbström (Grubba)  NO_WIDE_STRING(data); if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } if (THIS->mode < 0) Pike_error("Key schedule not initialized.\n"); if (THIS->dmode & NO_CDATA) Pike_error("More data not allowed before the iv is reset.\n"); result = begin_shared_string(data->len); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } if (!THIS->mode) {
0473d52014-05-11Henrik Grubbström (Grubba)  if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { THREADS_ALLOW(); gcm_encrypt(gcm_ctx, gcm_key, ctx, func, data->len, STR0(result), STR0(data)); THREADS_DISALLOW(); } else { gcm_encrypt(gcm_ctx, gcm_key, ctx, func, data->len, STR0(result), STR0(data)); }
ef84602014-04-26Henrik Grubbström (Grubba)  } else {
0473d52014-05-11Henrik Grubbström (Grubba)  if ((data->len >= CIPHER_THREADS_ALLOW_THRESHOLD) && (func != pike_crypt_func)) { THREADS_ALLOW(); gcm_decrypt(gcm_ctx, gcm_key, ctx, func, data->len, STR0(result), STR0(data)); THREADS_DISALLOW(); } else { gcm_decrypt(gcm_ctx, gcm_key, ctx, func, data->len, STR0(result), STR0(data)); }
ef84602014-04-26Henrik Grubbström (Grubba)  } THIS->dmode |= NO_ADATA; if (data->len & (GCM_BLOCK_SIZE - 1)) THIS->dmode |= NO_CDATA; pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } /*! @decl string(0..255) digest() *! *! Generate a message digest for the data accumulated so far. *! *! @note *! @[set_iv()] needs to be called to start the next message. *! *! @seealso *! @[update()], @[digest()] */ PIKEFUN string(0..255) digest() { struct pike_string *result; ONERROR uwp;
fd073e2014-06-23Henrik Grubbström (Grubba)  pike_nettle_crypt_func func = pike_crypt_func;
ef84602014-04-26Henrik Grubbström (Grubba)  void *ctx = THIS->object; if (!THIS->object || !THIS->object->prog) { Pike_error("Lookup in destructed object.\n"); } if (THIS->mode < 0) Pike_error("Key schedule not initialized.\n"); result = begin_shared_string(GCM_BLOCK_SIZE); SET_ONERROR (uwp, do_free_string, result); if (THIS->crypt_state && THIS->crypt_state->crypt) { func = THIS->crypt_state->crypt; ctx = THIS->crypt_state->ctx; } gcm_digest(&THIS->gcm_ctx, &THIS->gcm_key, ctx, func, GCM_BLOCK_SIZE, STR0(result)); THIS->dmode |= NO_ADATA | NO_CDATA; pop_n_elems(args); push_string(end_shared_string(result)); UNSET_ONERROR(uwp); } }
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @endclass State
ef84602014-04-26Henrik Grubbström (Grubba)  */ }
9b69512014-05-01Henrik Grubbström (Grubba)  /*! @endmodule GCM
ef84602014-04-26Henrik Grubbström (Grubba)  */ #endif /* HAVE_NETTLE_GCM_H */
9ce28d2014-06-09Henrik Grubbström (Grubba)  /* NB: Declare the storage explicitly to avoid having it declared * inside the #ifdef above. */ DECLARE_STORAGE;
ef84602014-04-26Henrik Grubbström (Grubba)  INIT {
8a91cb2016-04-14Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher16_cq__KW_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER16->KW = Pike_sp[-1].u.object); } pop_stack();
9b69512014-05-01Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher16_cq__CCM_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER16->CCM = Pike_sp[-1].u.object); } pop_stack(); apply_current(Nettle_BlockCipher16_cq__CCM8_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) { add_ref(THIS_NETTLE_BLOCKCIPHER16->CCM8 = Pike_sp[-1].u.object); } pop_stack();
9ce28d2014-06-09Henrik Grubbström (Grubba) #ifdef HAVE_NETTLE_EAX_H apply_current(Nettle_BlockCipher16_cq__EAX_program_fun_num, 0); if (TYPEOF(Pike_sp[-1]) == T_OBJECT) {
51f0802017-06-04Henrik Grubbström (Grubba)  add_ref(THIS_NETTLE_BLOCKCIPHER16->EAX_object = Pike_sp[-1].u.object);
9ce28d2014-06-09Henrik Grubbström (Grubba)  } pop_stack(); #endif
ef84602014-04-26Henrik Grubbström (Grubba) #ifdef HAVE_NETTLE_GCM_H
3747282014-04-30Henrik Grubbström (Grubba)  apply_current(Nettle_BlockCipher16_cq__GCM_program_fun_num, 0);
ef84602014-04-26Henrik Grubbström (Grubba)  if (TYPEOF(Pike_sp[-1]) == T_OBJECT) {
3747282014-04-30Henrik Grubbström (Grubba)  add_ref(THIS_NETTLE_BLOCKCIPHER16->GCM = Pike_sp[-1].u.object);
ef84602014-04-26Henrik Grubbström (Grubba)  } pop_stack(); #endif } }
3747282014-04-30Henrik Grubbström (Grubba) /*! @endclass BlockCipher16
ef84602014-04-26Henrik Grubbström (Grubba)  */
3747282014-04-30Henrik Grubbström (Grubba) #define BLOCKCIPHER16_CIPHER_INHERIT (BLOCKCIPHER_CIPHER_INHERIT + 1)
662c982003-11-09Niels Möller static void pike_aes_set_encrypt_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
c735c02003-03-18Niels Möller {
662c982003-11-09Niels Möller  if (length == 16 || length == 24 || length == 32)
20e2ef2005-12-12Martin Nilsson  aes_set_encrypt_key(ctx, length, (const uint8_t *)key);
662c982003-11-09Niels Möller  else
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("AES: Bad keysize for AES.\n");
662c982003-11-09Niels Möller } static void pike_aes_set_decrypt_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
662c982003-11-09Niels Möller { if (length == 16 || length == 24 || length == 32)
20e2ef2005-12-12Martin Nilsson  aes_set_decrypt_key(ctx, length, (const uint8_t *)key);
662c982003-11-09Niels Möller  else
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("AES: Bad keysize for AES.\n");
c735c02003-03-18Niels Möller }
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE BLOCK16_MODE
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME AES #cmod_define NETTLE_NAME aes
3747282014-04-30Henrik Grubbström (Grubba) #cmod_include "cipher.H"
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME
c735c02003-03-18Niels Möller 
07e4b62013-10-28Henrik Grubbström (Grubba) static void pike_arctwo_set_key(void *ctx, ptrdiff_t length, const char *key, int ekb) {
9b69512014-05-01Henrik Grubbström (Grubba)  if (!ekb) ekb = 128;
07e4b62013-10-28Henrik Grubbström (Grubba)  if (length < ARCTWO_MIN_KEY_SIZE || length > ARCTWO_MAX_KEY_SIZE) Pike_error("ARCTWO: Bad keysize for ARCTWO.\n"); arctwo_set_key_ekb(ctx, length, (const uint8_t *)key, ekb); } #define pike_arctwo_set_encrypt_key pike_arctwo_set_key #define pike_arctwo_set_decrypt_key pike_arctwo_set_key /*! @class ARCTWO *! *! Implementation of the ARCTWO cipher. *! */ PIKECLASS ARCTWO {
3747282014-04-30Henrik Grubbström (Grubba)  /*! @decl inherit BlockCipher
07e4b62013-10-28Henrik Grubbström (Grubba)  */
2194f92018-11-04Marcus Comstedt  INHERIT BlockCipher;
07e4b62013-10-28Henrik Grubbström (Grubba) 
6a63542013-10-31Henrik Grubbström (Grubba)  static const struct pike_cipher pike_arctwo = _PIKE_CIPHER(arctwo, ARCTWO);
07e4b62013-10-28Henrik Grubbström (Grubba)  INIT {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *cipher;
3747282014-04-30Henrik Grubbström (Grubba)  ASSIGN_CURRENT_STORAGE(cipher, struct Nettle_Cipher_struct, BLOCKCIPHER_CIPHER_INHERIT + 1,
895c722014-03-29Henrik Grubbström (Grubba)  Nettle_Cipher_program);
07e4b62013-10-28Henrik Grubbström (Grubba)  cipher->meta = &pike_arctwo; } /*! @class State *! *! State for PIKE_NAME encyption. *! */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit Cipher::State */
6a63542013-10-31Henrik Grubbström (Grubba)  static int f_ARCTWO_State_inherited_set_encrypt_key_fun_num = -1; static int f_ARCTWO_State_inherited_set_decrypt_key_fun_num = -1;
8f28a22013-10-28Henrik Grubbström (Grubba) 
07e4b62013-10-28Henrik Grubbström (Grubba)  EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the Cipher.State class (if any) that our parent * may contain via its inherit of Cipher via BlockCipher.
07e4b62013-10-28Henrik Grubbström (Grubba)  */
2fe8e02017-08-04Henrik Grubbström (Grubba)  if( lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING) )
b715e52017-07-31Martin Nilsson  { f_ARCTWO_State_inherited_set_encrypt_key_fun_num = really_low_reference_inherited_identifier(NULL, 1, f_Nettle_Cipher_State_set_encrypt_key_fun_num); f_ARCTWO_State_inherited_set_decrypt_key_fun_num = really_low_reference_inherited_identifier(NULL, 1, f_Nettle_Cipher_State_set_decrypt_key_fun_num);
07e4b62013-10-28Henrik Grubbström (Grubba)  } } CVAR struct arctwo_ctx arctwo; INIT {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_State_struct *state; ASSIGN_CURRENT_STORAGE(state, struct Nettle_Cipher_State_struct, 1, Nettle_Cipher_State_program);
07e4b62013-10-28Henrik Grubbström (Grubba)  state->ctx = &THIS->arctwo; }
f6a6ad2013-12-08Henrik Grubbström (Grubba)  /*! @decl State set_encrypt_key(string(0..255) key, int|void ekb)
07e4b62013-10-28Henrik Grubbström (Grubba)  *! *! Initializes the object for encryption. The @[key] memory will be *! cleared before released. *! *! @param ekb *! The effective number of bits in the key. *! @int *! @value UNDEFINED *! Derive from the key size (ie @expr{8 * sizeof(key)@}). *! @value 0 *! Convenience alias for max (ie @expr{1024@}). *! @value 1..1024 *! Reduce the effective key size to the specified number of bits. *! @endint *! *! @seealso *! @[set_decrypt_key], @[crypt] */
f6a6ad2013-12-08Henrik Grubbström (Grubba)  PIKEFUN object set_encrypt_key(string(0..255) key, void|int(0..1024) ekb)
07e4b62013-10-28Henrik Grubbström (Grubba)  optflags OPT_SIDE_EFFECT;
895c722014-03-29Henrik Grubbström (Grubba)  rawtype tFunc(tStr8 tOr(tInt, tVoid), tObjImpl_NETTLE_CIPHER_STATE);
07e4b62013-10-28Henrik Grubbström (Grubba)  { NO_WIDE_STRING(key); if (!ekb) { if (args > 1) pop_n_elems(args - 1); push_int(key->len * 8); args = 2; }
6a63542013-10-31Henrik Grubbström (Grubba)  apply_current(f_ARCTWO_State_inherited_set_encrypt_key_fun_num, args);
07e4b62013-10-28Henrik Grubbström (Grubba)  }
f6a6ad2013-12-08Henrik Grubbström (Grubba)  /*! @decl State set_decrypt_key(string(0..255) key, void|int ekb)
07e4b62013-10-28Henrik Grubbström (Grubba)  *! *! Initializes the object for decryption. The @[key] memory will be *! cleared before released. *! *! @param ekb *! The effective number of bits in the key. *! @int *! @value UNDEFINED *! Derive from the key size (ie @expr{8 * sizeof(key)@}). *! @value 0 *! Convenience alias for max (ie @expr{1024@}). *! @value 1..1024 *! Reduce the effective key size to the specified number of bits. *! @endint *! *! @seealso *! @[set_encrypt_key], @[crypt] */
f6a6ad2013-12-08Henrik Grubbström (Grubba)  PIKEFUN object set_decrypt_key(string(0..255) key, void|int ekb)
07e4b62013-10-28Henrik Grubbström (Grubba)  optflags OPT_SIDE_EFFECT;
895c722014-03-29Henrik Grubbström (Grubba)  rawtype tFunc(tStr8 tOr(tInt, tVoid), tObjImpl_NETTLE_CIPHER_STATE);
07e4b62013-10-28Henrik Grubbström (Grubba)  { NO_WIDE_STRING(key); if (!ekb) { if (args > 1) pop_n_elems(args - 1); push_int(key->len * 8); args = 2; }
6a63542013-10-31Henrik Grubbström (Grubba)  apply_current(f_ARCTWO_State_inherited_set_decrypt_key_fun_num, args);
07e4b62013-10-28Henrik Grubbström (Grubba)  } } /*! @endclass State */ } /*! @endclass ARCTWO */
662c982003-11-09Niels Möller static void pike_arcfour_set_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
8417e52003-08-24Martin Nilsson {
662c982003-11-09Niels Möller  if (length < ARCFOUR_MIN_KEY_SIZE || length > ARCFOUR_MAX_KEY_SIZE)
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("ARCFOUR: Bad keysize for ARCFOUR.\n");
662c982003-11-09Niels Möller 
20e2ef2005-12-12Martin Nilsson  arcfour_set_key(ctx, length, (const uint8_t *)key);
8417e52003-08-24Martin Nilsson }
f8b7242015-04-17Martin Nilsson 
662c982003-11-09Niels Möller #define pike_arcfour_set_encrypt_key pike_arcfour_set_key #define pike_arcfour_set_decrypt_key pike_arcfour_set_key #define arcfour_encrypt arcfour_crypt #define arcfour_decrypt arcfour_crypt
5040d82003-11-29Martin Nilsson #define ARCFOUR_BLOCK_SIZE 1
8417e52003-08-24Martin Nilsson 
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE STREAM_MODE
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME ARCFOUR #cmod_define NETTLE_NAME arcfour #cmod_include "cipher.H" #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME
8417e52003-08-24Martin Nilsson 
85fc8e2011-04-21Martin Nilsson #ifdef HAVE_NETTLE_BLOWFISH_DECRYPT
dc4a972008-07-17Martin Stjernholm 
662c982003-11-09Niels Möller static void pike_blowfish_set_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
c1f5ab2003-08-26Martin Nilsson {
662c982003-11-09Niels Möller  if (length < BLOWFISH_MIN_KEY_SIZE || length > BLOWFISH_MAX_KEY_SIZE)
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("BLOWFISH: Bad keysize for BLOWFISH.\n");
20e2ef2005-12-12Martin Nilsson  if (!blowfish_set_key(ctx, length, (const uint8_t *)key))
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("BLOWFISH: Key is weak (and force flag is currently ignored).\n");
c1f5ab2003-08-26Martin Nilsson }
662c982003-11-09Niels Möller #define pike_blowfish_set_encrypt_key pike_blowfish_set_key #define pike_blowfish_set_decrypt_key pike_blowfish_set_key
c1f5ab2003-08-26Martin Nilsson 
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE BLOCK_MODE
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME BLOWFISH #cmod_define NETTLE_NAME blowfish #cmod_include "cipher.H" #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME
1b34712003-08-25Martin Nilsson 
85fc8e2011-04-21Martin Nilsson #endif /* HAVE_NETTLE_BLOWFISH_DECRYPT */
dc4a972008-07-17Martin Stjernholm 
5ea7032014-04-21Henrik Grubbström (Grubba) #if !defined(CAMELLIA_KEY_SIZE) && defined(CAMELLIA128_KEY_SIZE) /* Nettle 3.0. * * Emulate the previous API where the Camellia variants were joined. */ #define CAMELLIA_KEY_SIZE CAMELLIA256_KEY_SIZE struct camellia_ctx { union { struct camellia128_ctx ctx128; struct camellia192_ctx ctx192; struct camellia256_ctx ctx256; } u; unsigned keylen; };
45382e2014-04-23Martin Nilsson static void camellia_set_encrypt_key(void *ctx, unsigned len, const uint8_t *key)
5ea7032014-04-21Henrik Grubbström (Grubba) { struct camellia_ctx *camellia_ctx = ctx; switch(len) { case CAMELLIA128_KEY_SIZE: camellia128_set_encrypt_key(&camellia_ctx->u.ctx128, key); break; case CAMELLIA192_KEY_SIZE: camellia192_set_encrypt_key(&camellia_ctx->u.ctx192, key); break; case CAMELLIA256_KEY_SIZE: camellia256_set_encrypt_key(&camellia_ctx->u.ctx256, key); break; default: Pike_fatal("Invalid keylength for Camellia: %d\n", len); break; } camellia_ctx->keylen = len; }
45382e2014-04-23Martin Nilsson static void camellia_set_decrypt_key(void *ctx, unsigned len, const uint8_t *key)
5ea7032014-04-21Henrik Grubbström (Grubba) { struct camellia_ctx *camellia_ctx = ctx; switch(len) { case CAMELLIA128_KEY_SIZE: camellia128_set_decrypt_key(&camellia_ctx->u.ctx128, key); break; case CAMELLIA192_KEY_SIZE: camellia192_set_decrypt_key(&camellia_ctx->u.ctx192, key); break; case CAMELLIA256_KEY_SIZE: camellia256_set_decrypt_key(&camellia_ctx->u.ctx256, key); break; default: Pike_fatal("Invalid keylength for Camellia: %d\n", len); break; } camellia_ctx->keylen = len; } static void camellia_crypt(struct camellia_ctx *ctx, unsigned length, uint8_t *dst, const uint8_t *src) { switch(ctx->keylen) { case CAMELLIA128_KEY_SIZE: camellia128_crypt(&ctx->u.ctx128, length, dst, src); break; case CAMELLIA192_KEY_SIZE: camellia192_crypt(&ctx->u.ctx192, length, dst, src); break; case 0: case CAMELLIA256_KEY_SIZE: camellia256_crypt(&ctx->u.ctx256, length, dst, src); break; default: Pike_fatal("Invalid keylength for Camellia: %d\n", ctx->keylen); break; } } #endif
650f102011-12-23Henrik Grubbström (Grubba) #ifdef CAMELLIA_KEY_SIZE
5ea7032014-04-21Henrik Grubbström (Grubba) #ifndef CAMELLIA128_KEY_SIZE #define CAMELLIA128_KEY_SIZE 16 #endif #ifndef CAMELLIA192_KEY_SIZE #define CAMELLIA192_KEY_SIZE 24 #endif #ifndef CAMELLIA256_KEY_SIZE #define CAMELLIA256_KEY_SIZE 32 #endif
650f102011-12-23Henrik Grubbström (Grubba) static void pike_camellia_set_encrypt_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
650f102011-12-23Henrik Grubbström (Grubba) {
5ea7032014-04-21Henrik Grubbström (Grubba)  if (length != CAMELLIA128_KEY_SIZE && length != CAMELLIA256_KEY_SIZE && length != CAMELLIA192_KEY_SIZE)
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("CAMELLIA: Bad keysize for CAMELLIA.\n");
650f102011-12-23Henrik Grubbström (Grubba)  camellia_set_encrypt_key(ctx, length, (const uint8_t *)key); } static void pike_camellia_set_decrypt_key(void *ctx, ptrdiff_t length, const char *key,
61017f2014-02-25Per Hedbor  int UNUSED(force))
650f102011-12-23Henrik Grubbström (Grubba) {
5ea7032014-04-21Henrik Grubbström (Grubba)  if (length != CAMELLIA128_KEY_SIZE && length != CAMELLIA256_KEY_SIZE && length != CAMELLIA192_KEY_SIZE)
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("CAMELLIA: Bad keysize for CAMELLIA.\n");
650f102011-12-23Henrik Grubbström (Grubba)  camellia_set_decrypt_key(ctx, length, (const uint8_t *)key); } #define camellia_encrypt camellia_crypt #define camellia_decrypt camellia_crypt
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE BLOCK16_MODE
650f102011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME CAMELLIA #cmod_define NETTLE_NAME camellia
3747282014-04-30Henrik Grubbström (Grubba) #cmod_include "cipher.H"
650f102011-12-23Henrik Grubbström (Grubba) #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME #endif /* CAMELLIA_KEY_SIZE */
662c982003-11-09Niels Möller static void pike_cast128_set_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
408f682003-07-29Martin Nilsson {
9e75202014-03-18Martin Nilsson #ifdef CAST5_MIN_KEY_SIZE if (length < CAST5_MIN_KEY_SIZE || length > CAST5_MAX_KEY_SIZE) Pike_error("CAST128_info: Bad keysize for CAST128.\n"); cast5_set_key(ctx, length, (const uint8_t *)key); #else
662c982003-11-09Niels Möller  if (length < CAST128_MIN_KEY_SIZE || length > CAST128_MAX_KEY_SIZE) Pike_error("CAST128_info: Bad keysize for CAST128.\n");
20e2ef2005-12-12Martin Nilsson  cast128_set_key(ctx, length, (const uint8_t *)key);
9e75202014-03-18Martin Nilsson #endif
408f682003-07-29Martin Nilsson }
662c982003-11-09Niels Möller #define pike_cast128_set_encrypt_key pike_cast128_set_key #define pike_cast128_set_decrypt_key pike_cast128_set_key
408f682003-07-29Martin Nilsson 
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE BLOCK_MODE
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME CAST128 #cmod_define NETTLE_NAME cast128 #cmod_include "cipher.H" #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME
408f682003-07-29Martin Nilsson 
24b0bd2014-04-18Henrik Grubbström (Grubba) #ifdef HAVE_NETTLE_CHACHA_H static void pike_chacha_set_key(void *ctx, ptrdiff_t length, const char *key, int UNUSED(force)) { if (length != CHACHA_KEY_SIZE) Pike_error("CHACHA: Bad keysize for CHACHA.\n"); chacha_set_key(ctx, (const uint8_t *)key); } #define pike_chacha_set_encrypt_key pike_chacha_set_key #define pike_chacha_set_decrypt_key pike_chacha_set_key #define chacha_encrypt chacha_crypt #define chacha_decrypt chacha_crypt /*! @class CHACHA *! *! Implementation of the CHACHA stream cipher. *! *! @note *! Note that this class is not available in all versions of Nettle. *! */ PIKECLASS CHACHA {
f30d992014-04-30Henrik Grubbström (Grubba)  /*! @decl inherit BlockCipher
24b0bd2014-04-18Henrik Grubbström (Grubba)  */
2194f92018-11-04Marcus Comstedt  INHERIT BlockCipher;
24b0bd2014-04-18Henrik Grubbström (Grubba)  static const struct pike_cipher pike_chacha = _PIKE_CIPHER(chacha, CHACHA); INIT { struct Nettle_Cipher_struct *cipher;
3747282014-04-30Henrik Grubbström (Grubba)  ASSIGN_CURRENT_STORAGE(cipher, struct Nettle_Cipher_struct, BLOCKCIPHER_CIPHER_INHERIT + 1,
24b0bd2014-04-18Henrik Grubbström (Grubba)  Nettle_Cipher_program); cipher->meta = &pike_chacha; } /*! @class State *! *! State for CHACHA encyption. *! */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { /*! @decl inherit Cipher::State */ EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the Cipher.State class (if any) that our parent * may contain via its inherit of Cipher via BlockCipher.
24b0bd2014-04-18Henrik Grubbström (Grubba)  */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
24b0bd2014-04-18Henrik Grubbström (Grubba)  } CVAR struct chacha_ctx chacha; /*! @decl string(0..255) crypt(string(0..255) data) *! *! Encrypts or decrypts data, using the current key. Neither the *! input nor output data is automatically memory scrubbed, *! unless @[String.secure] has been called on them. *! *! @param data *! Usually an integral number of blocks, except for the last *! segement in a run. The decoder must get partial blocks *! at the same places as the encoder, otherwise they will get *! out of sync. *! *! @returns *! The encrypted or decrypted data. */ PIKEFUN string(0..255) crypt (string(0..255) data) optflags OPT_EXTERNAL_DEPEND | OPT_SIDE_EFFECT; { struct pike_string *s; NO_WIDE_STRING(data); /* NB: Differs from default in that the block size * isn't enforced. * * To simplify the code we also skip the indirection * via the Cipher class and its State. */ s = begin_shared_string(data->len); chacha_crypt(&THIS->chacha, data->len, (uint8_t *)s->str, (const uint8_t *)data->str); s = end_shared_string(s); push_string(s); } /*! @decl object set_iv(string(0..255) iv) *! *! Set the initialization vector (aka nonce) and reset *! the block counter to zero. *! *! @param iv *! An 8-byte long string which is only to be used *! once for every key. *! *! @note *! This function MUST be called in addition to *! @[set_encrypt_key()] or @[set_decrypt_key()]. *! *! @note *! The same @[iv] should NEVER be reused with the same key! */ PIKEFUN object set_iv(string(0..255) iv) rawtype tFunc(tStr8, tObjImpl_NETTLE_CIPHER_STATE); { NO_WIDE_STRING(iv); if (iv->len != CHACHA_NONCE_SIZE) Pike_error("CHACHA IV needs to be %d bytes.\n", CHACHA_NONCE_SIZE); iv->flags |= STRING_CLEAR_ON_EXIT;
be52b82014-05-13Martin Nilsson  chacha_set_nonce(&THIS->chacha, STR0(iv));
24b0bd2014-04-18Henrik Grubbström (Grubba)  push_object(this_object()); } INIT { struct Nettle_Cipher_State_struct *state; ASSIGN_CURRENT_STORAGE(state, struct Nettle_Cipher_State_struct, 1, Nettle_Cipher_State_program); state->ctx = &THIS->chacha; } } /*! @endclass State */ } /*! @endclass CHACHA */ #endif /* HAVE_NETTLE_CHACHA_H */
3b588a2003-10-05Martin Nilsson static void
662c982003-11-09Niels Möller pike_des_set_key(void *c, ptrdiff_t length, const char *key, int force)
3b588a2003-10-05Martin Nilsson {
662c982003-11-09Niels Möller  struct des_ctx *ctx = (struct des_ctx *) c; if (length != 8) Pike_error("DES_INFO: Bad keysize for DES.\n");
20e2ef2005-12-12Martin Nilsson  if (!des_set_key(ctx, (const uint8_t *)key))
662c982003-11-09Niels Möller  {
60000c2011-04-17Henrik Grubbström (Grubba) #ifndef DES_WEAK_KEY /* Nettle 2.1 and later. */ if (!force) Pike_error("DES_INFO: Key is weak.\n"); #else /* Nettle 2.0 and earlier. */
662c982003-11-09Niels Möller  switch (ctx->status) { case DES_WEAK_KEY: if (force) /* Use key anyway */ ctx->status = DES_OK; else Pike_error("DES_INFO: Key is weak.\n"); break;
13670c2015-05-25Martin Nilsson 
662c982003-11-09Niels Möller  case DES_BAD_PARITY: Pike_error("DES_INFO: Key has bad parity.\n"); default: Pike_error("DES_INFO: Unexpected error, please send a bug report.\n"); }
60000c2011-04-17Henrik Grubbström (Grubba) #endif
662c982003-11-09Niels Möller  }
3b588a2003-10-05Martin Nilsson }
662c982003-11-09Niels Möller #define pike_des_set_encrypt_key pike_des_set_key #define pike_des_set_decrypt_key pike_des_set_key
3b588a2003-10-05Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba) /*! @class DES
3b588a2003-10-05Martin Nilsson  *!
4d65952013-10-21Henrik Grubbström (Grubba)  *! Implementation of the Data Encryption Standard (DES) crypto algorithm. *! */ PIKECLASS DES
3b588a2003-10-05Martin Nilsson {
f30d992014-04-30Henrik Grubbström (Grubba)  /*! @decl inherit BlockCipher
4d65952013-10-21Henrik Grubbström (Grubba)  */
2194f92018-11-04Marcus Comstedt  INHERIT BlockCipher;
4d65952013-10-21Henrik Grubbström (Grubba) 
3b588a2003-10-05Martin Nilsson  INIT {
662c982003-11-09Niels Möller  static const struct pike_cipher pike_des = _PIKE_CIPHER(des, DES);
4d65952013-10-21Henrik Grubbström (Grubba)  /* FIXME: Ought to traverse the inherit graph for * the current program. */
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *cipher;
3747282014-04-30Henrik Grubbström (Grubba)  ASSIGN_CURRENT_STORAGE(cipher, struct Nettle_Cipher_struct, BLOCKCIPHER_CIPHER_INHERIT + 1,
895c722014-03-29Henrik Grubbström (Grubba)  Nettle_Cipher_program);
4d65952013-10-21Henrik Grubbström (Grubba)  cipher->meta = &pike_des;
3b588a2003-10-05Martin Nilsson  }
f6a6ad2013-12-08Henrik Grubbström (Grubba)  /*! @decl string(0..255) fix_parity(string(0..255) key)
fc06892003-11-27Martin Nilsson  *! Sets the last bit in every byte in @[key] to reflect the parity. *! If a seven byte key is used, it will be expanded into eight *! bytes. If a key longer than eight characters is used, it will *! be truncated to eight characters. */
4d65952013-10-21Henrik Grubbström (Grubba)  PIKEFUN string(0..255) fix_parity(string(0..255) key)
3b588a2003-10-05Martin Nilsson  { uint8_t buf[8];
5345c92013-05-19Martin Nilsson  NO_WIDE_STRING(key);
3b588a2003-10-05Martin Nilsson  if(key->len < 7) Pike_error("Key must be at least 7 characters.\n"); if(key->len == 7) { buf[0] = key->str[0]&254; buf[1] = (key->str[0]&1)<<7 | (key->str[1]>>1 & 126); buf[2] = (key->str[1]&3)<<6 | (key->str[2]>>2 & 62); buf[3] = (key->str[2]&7)<<5 | (key->str[3]>>3 & 30); buf[4] = (key->str[3]&15)<<4 | (key->str[4]>>4 & 14); buf[5] = (key->str[4]&31)<<3 | (key->str[5]>>5 & 6); buf[6] = (key->str[5]&63)<<2 | (key->str[6]>>6 & 2); buf[7] = (key->str[6]&127)<<1; } else
59fc9e2014-09-03Martin Nilsson  memcpy(buf, key->str, 8);
3b588a2003-10-05Martin Nilsson 
662c982003-11-09Niels Möller  des_fix_parity(8, buf, buf);
20e2ef2005-12-12Martin Nilsson  RETURN make_shared_binary_string((char *)buf, 8);
3b588a2003-10-05Martin Nilsson  }
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @class State *! *! State for DES encyption */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { DOCSTART() @decl inherit Cipher::State DOCEND()
3b588a2003-10-05Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba)  EXTRA
3b588a2003-10-05Martin Nilsson  {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the Cipher.State class (if any) that our parent * may contain via its inherit of Cipher via BlockCipher.
4d65952013-10-21Henrik Grubbström (Grubba)  */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
4d65952013-10-21Henrik Grubbström (Grubba)  }
3b588a2003-10-05Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba)  CVAR struct des_ctx des; INIT {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_State_struct *state; ASSIGN_CURRENT_STORAGE(state, struct Nettle_Cipher_State_struct, 1, Nettle_Cipher_State_program);
3b588a2003-10-05Martin Nilsson  state->ctx = &THIS->des; }
d55fde2003-11-28Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba)  PIKEFUN string(0..255) make_key() {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *info = GET_INFO(); struct Nettle_Cipher_State_struct *state; ASSIGN_CURRENT_STORAGE(state, struct Nettle_Cipher_State_struct, 1, Nettle_Cipher_State_program);
4d65952013-10-21Henrik Grubbström (Grubba)  assert(info);
95b3652013-11-29Martin Nilsson #ifndef DES_WEAK_KEY
f3ac582014-10-21Henrik Grubbström (Grubba)  /* NB: This loop temporarily leaks strings on the stack, * but we don't care, as it is a low probability, * and they will be cleaned up on return. */
95b3652013-11-29Martin Nilsson  do {
3aba5c2016-03-12Martin Nilsson  push_random_string(info->meta->key_size);
b7580b2014-10-20Henrik Grubbström (Grubba)  f_Nettle_DES_fix_parity(1);
95b3652013-11-29Martin Nilsson  } while( !des_set_key(state->ctx, (const uint8_t *)Pike_sp[-1].u.string->str) ); #else
3aba5c2016-03-12Martin Nilsson  push_random_string(info->meta->key_size);
895c722014-03-29Henrik Grubbström (Grubba)  f_Nettle_DES_fix_parity(1);
4d65952013-10-21Henrik Grubbström (Grubba)  info->meta->set_encrypt_key(state->ctx, Pike_sp[-1].u.string->len, Pike_sp[-1].u.string->str, 0);
95b3652013-11-29Martin Nilsson #endif
4d65952013-10-21Henrik Grubbström (Grubba) 
95b3652013-11-29Martin Nilsson  Pike_sp[-1].u.string->flags |= STRING_CLEAR_ON_EXIT;
4d65952013-10-21Henrik Grubbström (Grubba)  state->crypt = info->meta->encrypt; state->key_size = Pike_sp[-1].u.string->len; }
f6a6ad2013-12-08Henrik Grubbström (Grubba)  /*! @decl string(0..255) fix_parity(string(0..255) key)
4d65952013-10-21Henrik Grubbström (Grubba)  *! Sets the last bit in every byte in @[key] to reflect the parity. *! If a seven byte key is used, it will be expanded into eight *! bytes. If a key longer than eight characters is used, it will *! be truncated to eight characters. */ PIKEFUN string(0..255) fix_parity(string(0..255) key) {
895c722014-03-29Henrik Grubbström (Grubba)  apply_external(1, f_Nettle_DES_fix_parity_fun_num, args);
4d65952013-10-21Henrik Grubbström (Grubba)  }
e39ad62013-10-22Henrik Grubbström (Grubba)  }
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @endclass State */
3b588a2003-10-05Martin Nilsson }
4d65952013-10-21Henrik Grubbström (Grubba) /*! @endclass DES */
3b588a2003-10-05Martin Nilsson 
a980cf2014-09-10Henrik Grubbström (Grubba) DEFAULT_CMOD_STORAGE void f_Nettle_DES3_fix_parity(INT32);
8048062003-12-06Martin Nilsson 
ab38b32003-10-08Martin Nilsson static void
662c982003-11-09Niels Möller pike_des3_set_key(void *c,
b0fb072004-10-08Martin Nilsson  ptrdiff_t length, const char *key,
662c982003-11-09Niels Möller  int force)
ab38b32003-10-08Martin Nilsson {
662c982003-11-09Niels Möller  struct des3_ctx *ctx = (struct des3_ctx *) c; int i;
274f7d2004-01-23Martin Nilsson  char nkotb[24];
5e68dc2003-11-29Martin Nilsson  switch( length ) { case 7+7: push_string(make_shared_binary_string(key, length));
5e9fc02015-08-18Per Hedbor  push_static_text("1234567");
5e68dc2003-11-29Martin Nilsson  f_add(2);
1c213a2014-03-29Martin Nilsson  f_Nettle_DES3_fix_parity(1);
5e68dc2003-11-29Martin Nilsson 
59fc9e2014-09-03Martin Nilsson  memcpy(nkotb, Pike_sp[-1].u.string->str, 8+8);
5e68dc2003-11-29Martin Nilsson  pop_stack(); key = nkotb; length = 8+8; /* fallthrough */ case 8+8: push_string(make_shared_binary_string(key, length)); push_string(make_shared_binary_string(key, length)); push_int(0); push_int(7); o_range(); f_add(2);
59fc9e2014-09-03Martin Nilsson  memcpy(nkotb, Pike_sp[-1].u.string->str, 8+8+8);
5e68dc2003-11-29Martin Nilsson  pop_stack(); key = nkotb; length = 8+8+8; break; case 7+7+7: push_string(make_shared_binary_string(key, length));
1c213a2014-03-29Martin Nilsson  f_Nettle_DES3_fix_parity(1);
59fc9e2014-09-03Martin Nilsson  memcpy(nkotb, Pike_sp[-1].u.string->str, 8+8+8);
5e68dc2003-11-29Martin Nilsson  pop_stack(); key = nkotb; length = 8+8+8; break; case 8+8+8: break; default:
662c982003-11-09Niels Möller  Pike_error("DES3_INFO: Bad keysize for DES3.\n");
5e68dc2003-11-29Martin Nilsson  break; }
662c982003-11-09Niels Möller 
95b3652013-11-29Martin Nilsson #ifndef DES_WEAK_KEY if( !des3_set_key(ctx, (const uint8_t *)key) && !force ) Pike_error("DES3_INFO: Key is weak.\n"); #else
662c982003-11-09Niels Möller  /* The hack of resetting ctx->status to use a weak key doesn't * currently work with nettle's des3_set_key function. So we set the * individual keys by ourself. */ for (i = 0; i<3; i++, key += DES_KEY_SIZE)
20e2ef2005-12-12Martin Nilsson  if (!des_set_key(&ctx->des[i], (const uint8_t *)key))
60000c2011-04-17Henrik Grubbström (Grubba)  { /* Nettle 2.0 and earlier. */
662c982003-11-09Niels Möller  switch (ctx->des[i].status) { case DES_WEAK_KEY: if (force) /* Use key anyway */ ctx->des[i].status = DES_OK; else Pike_error("DES3_INFO: Key is weak.\n"); break;
13670c2015-05-25Martin Nilsson 
662c982003-11-09Niels Möller  case DES_BAD_PARITY: Pike_error("DES3_INFO: Key has bad parity.\n"); default: Pike_error("DES3_INFO: Unexpected error, please send a bug report.\n");
60000c2011-04-17Henrik Grubbström (Grubba)  }
662c982003-11-09Niels Möller  }
95b3652013-11-29Martin Nilsson #endif
ab38b32003-10-08Martin Nilsson }
662c982003-11-09Niels Möller #define pike_des3_set_encrypt_key pike_des3_set_key #define pike_des3_set_decrypt_key pike_des3_set_key
ab38b32003-10-08Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba) /*! @class DES3
ab38b32003-10-08Martin Nilsson  *!
4d65952013-10-21Henrik Grubbström (Grubba)  *! Implementation of the DES3 cipher algorithm. *! */ PIKECLASS DES3
ab38b32003-10-08Martin Nilsson {
f30d992014-04-30Henrik Grubbström (Grubba)  /*! @decl inherit BlockCipher
4d65952013-10-21Henrik Grubbström (Grubba)  */
2194f92018-11-04Marcus Comstedt  INHERIT BlockCipher;
4d65952013-10-21Henrik Grubbström (Grubba) 
ab38b32003-10-08Martin Nilsson  INIT {
662c982003-11-09Niels Möller  static const struct pike_cipher pike_des3 = _PIKE_CIPHER(des3, DES3);
4d65952013-10-21Henrik Grubbström (Grubba)  /* FIXME: Ought to traverse the inherit graph for * the current program. */
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *cipher;
3747282014-04-30Henrik Grubbström (Grubba)  ASSIGN_CURRENT_STORAGE(cipher, struct Nettle_Cipher_struct, BLOCKCIPHER_CIPHER_INHERIT + 1,
895c722014-03-29Henrik Grubbström (Grubba)  Nettle_Cipher_program);
4d65952013-10-21Henrik Grubbström (Grubba)  cipher->meta = &pike_des3;
ab38b32003-10-08Martin Nilsson  }
d55fde2003-11-28Martin Nilsson 
f6a6ad2013-12-08Henrik Grubbström (Grubba)  /*! @decl string(0..255) fix_parity(string(0..255) key)
d55fde2003-11-28Martin Nilsson  *! Sets the last bit in every byte in @[key] to reflect the parity. *! If a 21 byte key is used, it will be expanded into 24 *! bytes. If a key longer than 24 characters is used, it will *! be truncated to 24 characters. */
4d65952013-10-21Henrik Grubbström (Grubba)  PIKEFUN string(0..255) fix_parity(string(0..255) key)
d55fde2003-11-28Martin Nilsson  {
675b552003-11-29Martin Nilsson  INT32 i;
d55fde2003-11-28Martin Nilsson  struct array *arr;
5345c92013-05-19Martin Nilsson  NO_WIDE_STRING(key);
d55fde2003-11-28Martin Nilsson  if(key->len < 24 && key->len != 21) Pike_error("Key must be 21 or >=24 characters.\n"); /* Split the string */ if(key->len==21) push_int(7); else push_int(8); f_divide(2); arr = Pike_sp[-1].u.array; add_ref(arr); pop_stack(); /* fix_parity for every subkey */ for(i=0; i<3; i++) {
675b552003-11-29Martin Nilsson  push_int(0); array_index(&Pike_sp[-1], arr, i);
895c722014-03-29Henrik Grubbström (Grubba)  f_Nettle_DES_fix_parity(1);
d55fde2003-11-28Martin Nilsson  }
675b552003-11-29Martin Nilsson  free_array(arr);
d55fde2003-11-28Martin Nilsson  /* Join the subkeys */ f_add(3); }
ab38b32003-10-08Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @class State *! *! State for DES3 encyption */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; { DOCSTART() @decl inherit Cipher::State DOCEND()
ab38b32003-10-08Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba)  EXTRA
ab38b32003-10-08Martin Nilsson  {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the Cipher.State class (if any) that our parent * may contain via its inherit of Cipher via BlockCipher.
4d65952013-10-21Henrik Grubbström (Grubba)  */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
4d65952013-10-21Henrik Grubbström (Grubba)  }
ab38b32003-10-08Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba)  CVAR struct des3_ctx des3; INIT {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_State_struct *state; ASSIGN_CURRENT_STORAGE(state, struct Nettle_Cipher_State_struct, 1, Nettle_Cipher_State_program);
ab38b32003-10-08Martin Nilsson  state->ctx = &THIS->des3; }
d55fde2003-11-28Martin Nilsson 
4d65952013-10-21Henrik Grubbström (Grubba)  PIKEFUN string(0..255) make_key() {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *info = GET_INFO(); struct Nettle_Cipher_State_struct *state; ASSIGN_CURRENT_STORAGE(state, struct Nettle_Cipher_State_struct, 1, Nettle_Cipher_State_program);
4d65952013-10-21Henrik Grubbström (Grubba)  assert(info);
95b3652013-11-29Martin Nilsson #ifndef DES_WEAK_KEY
f3ac582014-10-21Henrik Grubbström (Grubba)  /* NB: This loop temporarily leaks strings on the stack, * but we don't care, as it is a low probability, * and they will be cleaned up on return. */
95b3652013-11-29Martin Nilsson  do {
3aba5c2016-03-12Martin Nilsson  push_random_string(info->meta->key_size);
b7580b2014-10-20Henrik Grubbström (Grubba)  f_Nettle_DES3_fix_parity(1);
95b3652013-11-29Martin Nilsson  } while( !des3_set_key(state->ctx, (const uint8_t *)Pike_sp[-1].u.string->str) ); #else
3aba5c2016-03-12Martin Nilsson  push_random_string(info->meta->key_size);
1c213a2014-03-29Martin Nilsson  f_Nettle_DES3_fix_parity(1);
4d65952013-10-21Henrik Grubbström (Grubba)  info->meta->set_encrypt_key(state->ctx, Pike_sp[-1].u.string->len, Pike_sp[-1].u.string->str, 0);
95b3652013-11-29Martin Nilsson #endif
4d65952013-10-21Henrik Grubbström (Grubba) 
95b3652013-11-29Martin Nilsson  Pike_sp[-1].u.string->flags |= STRING_CLEAR_ON_EXIT;
4d65952013-10-21Henrik Grubbström (Grubba)  state->crypt = info->meta->encrypt; state->key_size = Pike_sp[-1].u.string->len; }
d55fde2003-11-28Martin Nilsson  }
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @endclass State */
ab38b32003-10-08Martin Nilsson }
4d65952013-10-21Henrik Grubbström (Grubba)  /*! @endclass DES3 */
ab38b32003-10-08Martin Nilsson 
f3b8d42013-11-12Martin Nilsson #ifdef HAVE_NETTLE_SALSA20_CRYPT static void pike_salsa20_set_key(void *ctx, ptrdiff_t length, const char *key, int UNUSED(force)) {
2beea72013-11-12Henrik Grubbström (Grubba)  if ((length != SALSA20_MIN_KEY_SIZE) && (length != SALSA20_MAX_KEY_SIZE))
f3b8d42013-11-12Martin Nilsson  Pike_error("SALSA20: Bad keysize for SALSA20.\n"); salsa20_set_key(ctx, length, (const uint8_t *)key); } #define pike_salsa20_set_encrypt_key pike_salsa20_set_key #define pike_salsa20_set_decrypt_key pike_salsa20_set_key #define salsa20_encrypt salsa20_crypt #define salsa20_decrypt salsa20_crypt
2beea72013-11-12Henrik Grubbström (Grubba) /*! @class SALSA20
f3b8d42013-11-12Martin Nilsson  *! *! Implementation of the SALSA20 cipher. *! */ PIKECLASS SALSA20 {
f30d992014-04-30Henrik Grubbström (Grubba)  /*! @decl inherit BlockCipher
f3b8d42013-11-12Martin Nilsson  */
2194f92018-11-04Marcus Comstedt  INHERIT BlockCipher;
f3b8d42013-11-12Martin Nilsson  static const struct pike_cipher pike_salsa20 = _PIKE_CIPHER(salsa20, SALSA20); INIT {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *cipher;
3747282014-04-30Henrik Grubbström (Grubba)  ASSIGN_CURRENT_STORAGE(cipher, struct Nettle_Cipher_struct, BLOCKCIPHER_CIPHER_INHERIT + 1,
895c722014-03-29Henrik Grubbström (Grubba)  Nettle_Cipher_program);
f3b8d42013-11-12Martin Nilsson  cipher->meta = &pike_salsa20; }
2beea72013-11-12Henrik Grubbström (Grubba)  /*! @class State
f3b8d42013-11-12Martin Nilsson  *!
2beea72013-11-12Henrik Grubbström (Grubba)  *! State for SALSA20 encyption.
f3b8d42013-11-12Martin Nilsson  *! */ PIKECLASS State program_flags PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; {
2beea72013-11-12Henrik Grubbström (Grubba)  /*! @decl inherit Cipher::State
f3b8d42013-11-12Martin Nilsson  */ EXTRA {
2fe8e02017-08-04Henrik Grubbström (Grubba)  /* Perform an inherit of the Cipher.State class (if any) that our parent * may contain via its inherit of Cipher via BlockCipher.
f3b8d42013-11-12Martin Nilsson  */
2fe8e02017-08-04Henrik Grubbström (Grubba)  lexical_inherit(1, MK_STRING("State"), 0, REPORT_WARNING);
f3b8d42013-11-12Martin Nilsson  } CVAR struct salsa20_ctx salsa20;
2beea72013-11-12Henrik Grubbström (Grubba)  /*! @decl object set_iv(string(0..255) iv) *! *! Set the initialization vector (aka nonce) and reset *! the block counter to zero. *! *! @param iv *! An 8-byte long string which is only to be used *! once for every key. *! *! @note *! This function MUST be called in addition to *! @[set_encrypt_key()] or @[set_decrypt_key()]. *! *! @note *! The same @[iv] should NEVER be reused with the same key! */
f3b8d42013-11-12Martin Nilsson  PIKEFUN object set_iv(string(0..255) iv)
895c722014-03-29Henrik Grubbström (Grubba)  rawtype tFunc(tStr8, tObjImpl_NETTLE_CIPHER_STATE);
f3b8d42013-11-12Martin Nilsson  { NO_WIDE_STRING(iv);
2beea72013-11-12Henrik Grubbström (Grubba)  if (iv->len != SALSA20_IV_SIZE) Pike_error("SALSA20 IV needs to be %d bytes.\n", SALSA20_IV_SIZE);
f3b8d42013-11-12Martin Nilsson  iv->flags |= STRING_CLEAR_ON_EXIT;
1a31102014-05-13Henrik Grubbström (Grubba)  salsa20_set_iv(&THIS->salsa20, STR0(iv));
f3b8d42013-11-12Martin Nilsson  push_object(this_object()); } INIT {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_State_struct *state; ASSIGN_CURRENT_STORAGE(state, struct Nettle_Cipher_State_struct, 1, Nettle_Cipher_State_program);
f3b8d42013-11-12Martin Nilsson  state->ctx = &THIS->salsa20; } }
2beea72013-11-12Henrik Grubbström (Grubba)  /*! @endclass State
f3b8d42013-11-12Martin Nilsson  */ }
2beea72013-11-12Henrik Grubbström (Grubba) /*! @endclass SALSA20
f3b8d42013-11-12Martin Nilsson  */
7baa0a2013-11-18Martin Nilsson #ifdef salsa20r12_crypt
5369312013-11-15Henrik Grubbström (Grubba) #define pike_salsa20r12_set_encrypt_key pike_salsa20_set_encrypt_key #define pike_salsa20r12_set_decrypt_key pike_salsa20_set_decrypt_key #define salsa20r12_encrypt salsa20r12_crypt #define salsa20r12_decrypt salsa20r12_crypt #define salsa20r12_ctx salsa20_ctx #define SALSA20R12_BLOCK_SIZE SALSA20_BLOCK_SIZE #define SALSA20R12_KEY_SIZE SALSA20_KEY_SIZE /*! @class SALSA20R12 *! *! Implementation of the @[SALSA20] cipher reduced to 12 rounds. *! */ PIKECLASS SALSA20R12 { /*! @decl inherit SALSA20 */
2194f92018-11-04Marcus Comstedt  INHERIT SALSA20;
5369312013-11-15Henrik Grubbström (Grubba)  static const struct pike_cipher pike_salsa20r12 = _PIKE_CIPHER(salsa20r12, SALSA20R12); INIT {
895c722014-03-29Henrik Grubbström (Grubba)  struct Nettle_Cipher_struct *cipher;
3747282014-04-30Henrik Grubbström (Grubba)  /* NB: We know that BlockCipher is the first inherit of SALSA20. */ ASSIGN_CURRENT_STORAGE(cipher, struct Nettle_Cipher_struct, BLOCKCIPHER_CIPHER_INHERIT + 2,
895c722014-03-29Henrik Grubbström (Grubba)  Nettle_Cipher_program);
5369312013-11-15Henrik Grubbström (Grubba)  cipher->meta = &pike_salsa20r12; } } /*! @endclass SALSA20R12 */
7baa0a2013-11-18Martin Nilsson #endif /* salsa20r12_crypt */
5369312013-11-15Henrik Grubbström (Grubba) #endif /* HAVE_NETTLE_SALSA20_CRYPT */
f3b8d42013-11-12Martin Nilsson 
85fc8e2011-04-21Martin Nilsson #ifdef HAVE_NETTLE_SERPENT_DECRYPT
dc4a972008-07-17Martin Stjernholm 
662c982003-11-09Niels Möller static void pike_serpent_set_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
408f682003-07-29Martin Nilsson {
662c982003-11-09Niels Möller  if (length < SERPENT_MIN_KEY_SIZE || length > SERPENT_MAX_KEY_SIZE)
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("SERPENT: Bad keysize for SERPENT.\n");
13670c2015-05-25Martin Nilsson 
20e2ef2005-12-12Martin Nilsson  serpent_set_key(ctx, length, (const uint8_t *)key);
408f682003-07-29Martin Nilsson }
662c982003-11-09Niels Möller #define pike_serpent_set_encrypt_key pike_serpent_set_key #define pike_serpent_set_decrypt_key pike_serpent_set_key
408f682003-07-29Martin Nilsson 
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE BLOCK16_MODE
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME SERPENT #cmod_define NETTLE_NAME serpent
3747282014-04-30Henrik Grubbström (Grubba) #cmod_include "cipher.H"
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME
408f682003-07-29Martin Nilsson 
85fc8e2011-04-21Martin Nilsson #endif /* HAVE_NETTLE_SERPENT_DECRYPT */
dc4a972008-07-17Martin Stjernholm 
662c982003-11-09Niels Möller static void pike_twofish_set_key(void *ctx, ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
408f682003-07-29Martin Nilsson {
662c982003-11-09Niels Möller  if (length < TWOFISH_MIN_KEY_SIZE || length > TWOFISH_MAX_KEY_SIZE)
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("TWOFISH: Bad keysize for TWOFISH.\n");
662c982003-11-09Niels Möller 
20e2ef2005-12-12Martin Nilsson  twofish_set_key(ctx, length, (const uint8_t *)key);
408f682003-07-29Martin Nilsson }
662c982003-11-09Niels Möller #define pike_twofish_set_encrypt_key pike_twofish_set_key #define pike_twofish_set_decrypt_key pike_twofish_set_key
408f682003-07-29Martin Nilsson 
5667be2011-12-23Henrik Grubbström (Grubba) #define Twofish_BLOCK_SIZE TWOFISH_BLOCK_SIZE #define Twofish_KEY_SIZE TWOFISH_KEY_SIZE
408f682003-07-29Martin Nilsson 
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE BLOCK16_MODE
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME Twofish #cmod_define NETTLE_NAME twofish
3747282014-04-30Henrik Grubbström (Grubba) #cmod_include "cipher.H"
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME
408f682003-07-29Martin Nilsson 
82b27a2004-09-16Martin Nilsson #ifdef WITH_IDEA
fc06892003-11-27Martin Nilsson static void
766bc82004-10-16Marcus Agehall pike_idea_set_encrypt_key(void *ctx_v,
fc06892003-11-27Martin Nilsson  ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
fc06892003-11-27Martin Nilsson {
766bc82004-10-16Marcus Agehall  struct idea_ctx *ctx = ctx_v;
fc06892003-11-27Martin Nilsson  if (length == IDEA_KEY_SIZE)
5e68dc2003-11-29Martin Nilsson  idea_expand((unsigned INT16 *)ctx->ctx, (unsigned INT8 *)key);
fc06892003-11-27Martin Nilsson  else
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("IDEA: Bad keysize for IDEA.\n");
fc06892003-11-27Martin Nilsson } static void
766bc82004-10-16Marcus Agehall pike_idea_set_decrypt_key(void *ctx_v,
fc06892003-11-27Martin Nilsson  ptrdiff_t length, const char *key,
74dfe82012-12-30Jonas Walldén  int UNUSED(force))
fc06892003-11-27Martin Nilsson {
766bc82004-10-16Marcus Agehall  struct idea_ctx *ctx = ctx_v;
fc06892003-11-27Martin Nilsson  if (length == IDEA_KEY_SIZE) {
5e68dc2003-11-29Martin Nilsson  idea_expand((unsigned INT16 *)ctx->ctx, (unsigned INT8 *)key); idea_invert((unsigned INT16 *)ctx->ctx, (unsigned INT16 *)ctx->ctx);
fc06892003-11-27Martin Nilsson  } else
4d65952013-10-21Henrik Grubbström (Grubba)  Pike_error("IDEA: Bad keysize for IDEA.\n");
fc06892003-11-27Martin Nilsson } #define idea_encrypt idea_crypt_blocks #define idea_decrypt idea_crypt_blocks
3747282014-04-30Henrik Grubbström (Grubba) #cmod_define CIPHER_MODE BLOCK_MODE
5667be2011-12-23Henrik Grubbström (Grubba) #cmod_define PIKE_NAME IDEA #cmod_define NETTLE_NAME idea #cmod_include "cipher.H" #cmod_undef PIKE_NAME #cmod_undef NETTLE_NAME
fc06892003-11-27Martin Nilsson 
5667be2011-12-23Henrik Grubbström (Grubba) #endif /* WITH_IDEA */
fc06892003-11-27Martin Nilsson 
c735c02003-03-18Niels Möller /*! @endmodule Nettle */ void cipher_init(void) {
9b69512014-05-01Henrik Grubbström (Grubba)  nul13_string = begin_shared_string(13);
21b12a2014-09-03Martin Nilsson  memset(STR0(nul13_string), 0, 13);
9b69512014-05-01Henrik Grubbström (Grubba)  nul13_string = end_shared_string(nul13_string); nul16_string = begin_shared_string(16);
21b12a2014-09-03Martin Nilsson  memset(STR0(nul16_string), 0, 16);
9b69512014-05-01Henrik Grubbström (Grubba)  nul16_string = end_shared_string(nul16_string);
1c37ed2014-05-09Henrik Grubbström (Grubba) 
c735c02003-03-18Niels Möller  INIT;
3773e22014-03-19Martin Nilsson  ADD_INT_CONSTANT("PAD_SSL", PAD_SSL, 0); ADD_INT_CONSTANT("PAD_ISO_10126", PAD_ISO_10126, 0); ADD_INT_CONSTANT("PAD_ANSI_X923", PAD_ANSI_X923, 0); ADD_INT_CONSTANT("PAD_PKCS7", PAD_PKCS7, 0); ADD_INT_CONSTANT("PAD_ZERO", PAD_ZERO, 0);
82ba332014-03-26Martin Nilsson  ADD_INT_CONSTANT("PAD_TLS", PAD_TLS, 0);
c735c02003-03-18Niels Möller } void cipher_exit(void) { EXIT;
9b69512014-05-01Henrik Grubbström (Grubba)  free_string(nul16_string); free_string(nul13_string);
c735c02003-03-18Niels Möller } #endif /* HAVE_LIBNETTLE */