1 /*
   2  * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
   3  *
   4  * Permission to use, copy, modify, and distribute this software for any
   5  * purpose with or without fee is hereby granted, provided that the above
   6  * copyright notice and this permission notice appear in all copies.
   7  *
   8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15  */
  16 /*
  17  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  18  * Use is subject to license terms.
  19  */
  20 
  21 #include "includes.h"
  22 RCSID("$OpenBSD: cipher-ctr.c,v 1.4 2004/02/06 23:41:13 dtucker Exp $");
  23 
  24 #include <openssl/opensslconf.h>
  25 #include <openssl/evp.h>
  26 
  27 #include "log.h"
  28 #include "xmalloc.h"
  29 #include <openssl/aes.h>
  30 
  31 const EVP_CIPHER *evp_aes_128_ctr(void);
  32 void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
  33 
  34 struct ssh_aes_ctr_ctx
  35 {
  36         AES_KEY         aes_ctx;
  37         u_char          aes_counter[AES_BLOCK_SIZE];
  38 };
  39 
  40 /*
  41  * increment counter 'ctr',
  42  * the counter is of size 'len' bytes and stored in network-byte-order.
  43  * (LSB at ctr[len-1], MSB at ctr[0])
  44  */
  45 static void
  46 ssh_ctr_inc(u_char *ctr, u_int len)
  47 {
  48         int i;
  49 
  50         for (i = len - 1; i >= 0; i--)
  51                 if (++ctr[i])   /* continue on overflow */
  52                         return;
  53 }
  54 
  55 static int
  56 ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
  57     u_int len)
  58 {
  59         struct ssh_aes_ctr_ctx *c;
  60         u_int n = 0;
  61         u_char buf[AES_BLOCK_SIZE];
  62 
  63         if (len == 0)
  64                 return (1);
  65         if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
  66                 return (0);
  67 
  68         while ((len--) > 0) {
  69                 if (n == 0) {
  70                         AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
  71                         ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
  72                 }
  73                 *(dest++) = *(src++) ^ buf[n];
  74                 n = (n + 1) % AES_BLOCK_SIZE;
  75         }
  76         return (1);
  77 }
  78 
  79 static int
  80 ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
  81     int enc)
  82 {
  83         struct ssh_aes_ctr_ctx *c;
  84 
  85         if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
  86                 c = xmalloc(sizeof(*c));
  87                 EVP_CIPHER_CTX_set_app_data(ctx, c);
  88         }
  89         if (key != NULL)
  90                 AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
  91                      &c->aes_ctx);
  92         if (iv != NULL)
  93                 memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
  94         return (1);
  95 }
  96 
  97 static int
  98 ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
  99 {
 100         struct ssh_aes_ctr_ctx *c;
 101 
 102         if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
 103                 memset(c, 0, sizeof(*c));
 104                 xfree(c);
 105                 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
 106         }
 107         return (1);
 108 }
 109 
 110 void
 111 ssh_aes_ctr_iv(EVP_CIPHER_CTX *evp, int doset, u_char * iv, u_int len)
 112 {
 113         struct ssh_aes_ctr_ctx *c;
 114 
 115         if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
 116                 fatal("ssh_aes_ctr_iv: no context");
 117         if (doset)
 118                 memcpy(c->aes_counter, iv, len);
 119         else
 120                 memcpy(iv, c->aes_counter, len);
 121 }
 122 
 123 /*
 124  * Function fills an EVP_CIPHER structure for AES CTR functions based on the NID
 125  * and the key length.
 126  */
 127 static const EVP_CIPHER *
 128 evp_aes_ctr(const char *nid, int key_len, EVP_CIPHER *aes_ctr)
 129 {
 130         memset(aes_ctr, 0, sizeof(EVP_CIPHER));
 131         /*
 132          * If the PKCS#11 engine is used the AES CTR NIDs were dynamically
 133          * created during the engine initialization. If the engine is not used
 134          * we work with NID_undef's which is OK since in that case OpenSSL
 135          * doesn't use NIDs at all.
 136          */
 137         if ((aes_ctr->nid = OBJ_ln2nid(nid)) != NID_undef)
 138                 debug3("%s NID found", nid);
 139 
 140         aes_ctr->block_size = AES_BLOCK_SIZE;
 141         aes_ctr->iv_len = AES_BLOCK_SIZE;
 142         aes_ctr->key_len = key_len;
 143         aes_ctr->init = ssh_aes_ctr_init;
 144         aes_ctr->cleanup = ssh_aes_ctr_cleanup;
 145         aes_ctr->do_cipher = ssh_aes_ctr;
 146         aes_ctr->flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
 147             EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
 148         return (aes_ctr);
 149 }
 150 
 151 const EVP_CIPHER *
 152 evp_aes_128_ctr(void)
 153 {
 154         static EVP_CIPHER aes_ctr;
 155 
 156         return (evp_aes_ctr("aes-128-ctr", 16, &aes_ctr));
 157 }
 158 
 159 const EVP_CIPHER *
 160 evp_aes_192_ctr(void)
 161 {
 162         static EVP_CIPHER aes_ctr;
 163 
 164         return (evp_aes_ctr("aes-192-ctr", 24, &aes_ctr));
 165 }
 166 
 167 const EVP_CIPHER *
 168 evp_aes_256_ctr(void)
 169 {
 170         static EVP_CIPHER aes_ctr;
 171 
 172         return (evp_aes_ctr("aes-256-ctr", 32, &aes_ctr));
 173 }