Browse code

Refactored cipher functions

Signed-off-by: Adriaan de Jong <dejong@fox-it.com>
Acked-by: David Sommerseth <davids@redhat.com>
Signed-off-by: David Sommerseth <davids@redhat.com>

Adriaan de Jong authored on 2011/06/24 00:39:42
Showing 4 changed files
... ...
@@ -75,8 +75,8 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,
75 75
       if (ctx->cipher)
76 76
 	{
77 77
 	  uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH];
78
-	  const int iv_size = EVP_CIPHER_CTX_iv_length (ctx->cipher);
79
-	  const unsigned int mode = EVP_CIPHER_CTX_mode (ctx->cipher);  
78
+	  const int iv_size = cipher_ctx_iv_length (ctx->cipher);
79
+	  const unsigned int mode = cipher_ctx_mode (ctx->cipher);
80 80
 	  int outlen;
81 81
 
82 82
 	  if (mode == OPENVPN_MODE_CBC)
... ...
@@ -124,10 +124,10 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,
124 124
 	       format_hex (BPTR (buf), BLEN (buf), 80, &gc));
125 125
 
126 126
 	  /* cipher_ctx was already initialized with key & keylen */
127
-	  ASSERT (EVP_CipherInit_ov (ctx->cipher, NULL, NULL, iv_buf, DO_ENCRYPT));
127
+	  ASSERT (cipher_ctx_reset(ctx->cipher, iv_buf));
128 128
 
129 129
 	  /* Buffer overflow check */
130
-	  if (!buf_safe (&work, buf->len + EVP_CIPHER_CTX_block_size (ctx->cipher)))
130
+	  if (!buf_safe (&work, buf->len + cipher_ctx_block_size(ctx->cipher)))
131 131
 	    {
132 132
 	      msg (D_CRYPT_ERRORS, "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d cbs=%d",
133 133
 		   buf->capacity,
... ...
@@ -136,16 +136,16 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,
136 136
 		   work.capacity,
137 137
 		   work.offset,
138 138
 		   work.len,
139
-		   EVP_CIPHER_CTX_block_size (ctx->cipher));
139
+		   cipher_ctx_block_size (ctx->cipher));
140 140
 	      goto err;
141 141
 	    }
142 142
 
143 143
 	  /* Encrypt packet ID, payload */
144
-	  ASSERT (EVP_CipherUpdate_ov (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)));
144
+	  ASSERT (cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)));
145 145
 	  work.len += outlen;
146 146
 
147 147
 	  /* Flush the encryption buffer */
148
-	  ASSERT (EVP_CipherFinal (ctx->cipher, BPTR (&work) + outlen, &outlen));
148
+	  ASSERT(cipher_ctx_final(ctx->cipher, BPTR (&work) + outlen, &outlen));
149 149
 	  work.len += outlen;
150 150
 	  ASSERT (outlen == iv_size);
151 151
 
... ...
@@ -248,8 +248,8 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
248 248
 
249 249
       if (ctx->cipher)
250 250
 	{
251
-	  const unsigned int mode = EVP_CIPHER_CTX_mode (ctx->cipher);
252
-	  const int iv_size = EVP_CIPHER_CTX_iv_length (ctx->cipher);
251
+	  const unsigned int mode = cipher_ctx_mode (ctx->cipher);
252
+	  const int iv_size = cipher_ctx_iv_length (ctx->cipher);
253 253
 	  uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH];
254 254
 	  int outlen;
255 255
 
... ...
@@ -274,7 +274,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
274 274
 	    CRYPT_ERROR ("missing payload");
275 275
 
276 276
 	  /* ctx->cipher was already initialized with key & keylen */
277
-	  if (!EVP_CipherInit_ov (ctx->cipher, NULL, NULL, iv_buf, DO_DECRYPT))
277
+	  if (!cipher_ctx_reset (ctx->cipher, iv_buf))
278 278
 	    CRYPT_ERROR ("cipher init failed");
279 279
 
280 280
 	  /* Buffer overflow check (should never happen) */
... ...
@@ -282,12 +282,12 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,
282 282
 	    CRYPT_ERROR ("buffer overflow");
283 283
 
284 284
 	  /* Decrypt packet ID, payload */
285
-	  if (!EVP_CipherUpdate_ov (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)))
285
+	  if (!cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)))
286 286
 	    CRYPT_ERROR ("cipher update failed");
287 287
 	  work.len += outlen;
288 288
 
289 289
 	  /* Flush the decryption buffer */
290
-	  if (!EVP_CipherFinal (ctx->cipher, BPTR (&work) + outlen, &outlen))
290
+	  if (!cipher_ctx_final (ctx->cipher, BPTR (&work) + outlen, &outlen))
291 291
 	    CRYPT_ERROR ("cipher final failed");
292 292
 	  work.len += outlen;
293 293
 
... ...
@@ -383,41 +383,6 @@ crypto_adjust_frame_parameters(struct frame *frame,
383 383
 			    kt->hmac_length);
384 384
 }
385 385
 
386
-static void
387
-init_cipher (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
388
-	     struct key *key, const struct key_type *kt, int enc,
389
-	     const char *prefix)
390
-{
391
-  struct gc_arena gc = gc_new ();
392
-
393
-  EVP_CIPHER_CTX_init (ctx);
394
-  if (!EVP_CipherInit_ov (ctx, cipher, NULL, NULL, enc))
395
-    msg (M_SSLERR, "EVP cipher init #1");
396
-#ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH
397
-  if (!EVP_CIPHER_CTX_set_key_length (ctx, kt->cipher_length))
398
-    msg (M_SSLERR, "EVP set key size");
399
-#endif
400
-  if (!EVP_CipherInit_ov (ctx, NULL, key->cipher, NULL, enc))
401
-    msg (M_SSLERR, "EVP cipher init #2");
402
-
403
-  msg (D_HANDSHAKE, "%s: Cipher '%s' initialized with %d bit key",
404
-       prefix,
405
-       OBJ_nid2sn (EVP_CIPHER_CTX_nid (ctx)),
406
-       EVP_CIPHER_CTX_key_length (ctx) * 8);
407
-
408
-  /* make sure we used a big enough key */
409
-  ASSERT (EVP_CIPHER_CTX_key_length (ctx) <= kt->cipher_length);
410
-
411
-  dmsg (D_SHOW_KEYS, "%s: CIPHER KEY: %s", prefix,
412
-       format_hex (key->cipher, kt->cipher_length, 0, &gc));
413
-  dmsg (D_CRYPTO_DEBUG, "%s: CIPHER block_size=%d iv_size=%d",
414
-       prefix,
415
-       EVP_CIPHER_CTX_block_size (ctx),
416
-       EVP_CIPHER_CTX_iv_length (ctx));
417
-
418
-  gc_free (&gc);
419
-}
420
-
421 386
 /*
422 387
  * Build a struct key_type.
423 388
  */
... ...
@@ -476,8 +441,9 @@ init_key_ctx (struct key_ctx *ctx, struct key *key,
476 476
   CLEAR (*ctx);
477 477
   if (kt->cipher && kt->cipher_length > 0)
478 478
     {
479
-      ALLOC_OBJ (ctx->cipher, EVP_CIPHER_CTX);
480
-      init_cipher (ctx->cipher, kt->cipher, key, kt, enc, prefix);
479
+      ALLOC_OBJ(ctx->cipher, cipher_ctx_t);
480
+      cipher_ctx_init (ctx->cipher, key->cipher, kt->cipher_length,
481
+	  kt->cipher, enc, prefix);
481 482
     }
482 483
   if (kt->digest && kt->hmac_length > 0)
483 484
     {
... ...
@@ -492,8 +458,8 @@ free_key_ctx (struct key_ctx *ctx)
492 492
 {
493 493
   if (ctx->cipher)
494 494
     {
495
-      EVP_CIPHER_CTX_cleanup (ctx->cipher);
496
-      free (ctx->cipher);
495
+      cipher_ctx_cleanup(ctx->cipher);
496
+      free(ctx->cipher);
497 497
       ctx->cipher = NULL;
498 498
     }
499 499
   if (ctx->hmac)
... ...
@@ -182,6 +182,17 @@ struct key
182 182
                                 /**< %Key material for HMAC operations. */
183 183
 };
184 184
 
185
+
186
+/**
187
+ * Container for one set of OpenSSL cipher and/or HMAC contexts.
188
+ * @ingroup control_processor
189
+ */
190
+struct key_ctx
191
+{
192
+  cipher_ctx_t *cipher;      	/**< Generic cipher %context. */
193
+  hmac_ctx_t *hmac;               /**< Generic HMAC %context. */
194
+};
195
+
185 196
 #define KEY_DIRECTION_BIDIRECTIONAL 0 /* same keys for both directions */
186 197
 #define KEY_DIRECTION_NORMAL        1 /* encrypt with keys[0], decrypt with keys[1] */
187 198
 #define KEY_DIRECTION_INVERSE       2 /* encrypt with keys[1], decrypt with keys[0] */
... ...
@@ -224,16 +235,6 @@ struct key_direction_state
224 224
 };
225 225
 
226 226
 /**
227
- * Container for one set of OpenSSL cipher and/or HMAC contexts.
228
- * @ingroup control_processor
229
- */
230
-struct key_ctx
231
-{
232
-  EVP_CIPHER_CTX *cipher;       /**< OpenSSL cipher %context. */
233
-  HMAC_CTX *hmac;               /**< OpenSSL HMAC %context. */
234
-};
235
-
236
-/**
237 227
  * Container for two sets of OpenSSL cipher and/or HMAC contexts for both
238 228
  * sending and receiving directions.
239 229
  * @ingroup control_processor
... ...
@@ -313,9 +314,6 @@ void init_key_type (struct key_type *kt, const char *ciphername,
313 313
     bool ciphername_defined, const char *authname, bool authname_defined,
314 314
     int keysize, bool cfb_ofb_allowed, bool warn);
315 315
 
316
-/* enc parameter in init_key_ctx */
317
-#define DO_ENCRYPT 1
318
-#define DO_DECRYPT 0
319 316
 /*
320 317
  * Key context functions
321 318
  */
... ...
@@ -325,6 +323,7 @@ void init_key_ctx (struct key_ctx *ctx, struct key *key,
325 325
 		   const char *prefix);
326 326
 
327 327
 void free_key_ctx (struct key_ctx *ctx);
328
+
328 329
 void free_key_ctx_bi (struct key_ctx_bi *ctx);
329 330
 
330 331
 
... ...
@@ -401,7 +400,6 @@ bool openvpn_decrypt (struct buffer *buf, struct buffer work,
401 401
 
402 402
 /** @} name Functions for performing security operations on data channel packets */
403 403
 
404
-
405 404
 void crypto_adjust_frame_parameters(struct frame *frame,
406 405
 				    const struct key_type* kt,
407 406
 				    bool cipher_defined,
... ...
@@ -219,6 +219,106 @@ int cipher_kt_block_size (const cipher_kt_t *cipher_kt);
219 219
 bool cipher_kt_mode (const cipher_kt_t *cipher_kt);
220 220
 
221 221
 
222
+/**
223
+ *
224
+ * Generic cipher functions
225
+ *
226
+ */
227
+
228
+/**
229
+ * Initialise a cipher context, based on the given key and key type.
230
+ *
231
+ * @param ctx		Cipher context. May not be NULL
232
+ * @param key		Buffer containing the key to use
233
+ * @param key_len 	Length of the key, in bytes
234
+ * @param kt		Static cipher parameters to use
235
+ * @param enc		Whether to encrypt or decrypt (either
236
+ * 			\c POLARSSL_OP_ENCRYPT or \c POLARSSL_OP_DECRYPT).
237
+ * @param prefix	Prefix to use for output.
238
+ */
239
+void cipher_ctx_init (cipher_ctx_t *ctx, uint8_t *key, int key_len,
240
+    const cipher_kt_t *kt, int enc, const char *prefix);
241
+
242
+/**
243
+ * Cleanup the specified context.
244
+ *
245
+ * @param ctx	Cipher context to cleanup.
246
+ */
247
+void cipher_ctx_cleanup (cipher_ctx_t *ctx);
248
+
249
+/**
250
+ * Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is
251
+ * used.
252
+ *
253
+ * @param ctx	 	The cipher's context
254
+ *
255
+ * @return 		Size of the IV, in bytes, or \c 0 if the cipher does not
256
+ * 			use an IV or ctx was NULL.
257
+ */
258
+int cipher_ctx_iv_length (const cipher_ctx_t *ctx);
259
+
260
+/**
261
+ * Returns the block size of the cipher, in bytes.
262
+ *
263
+ * @param ctx	 	The cipher's context
264
+ *
265
+ * @return 		Block size, in bytes, or 0 if ctx was NULL.
266
+ */
267
+int cipher_ctx_block_size (const cipher_ctx_t *ctx);
268
+
269
+/**
270
+ * Returns the mode that the cipher runs in.
271
+ *
272
+ * @param ctx 		Cipher's context. May not be NULL.
273
+ *
274
+ * @return 		Cipher mode, either \c OPENVPN_MODE_CBC, \c
275
+ * 			OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB
276
+ */
277
+int cipher_ctx_mode (const cipher_ctx_t *ctx);
278
+
279
+/**
280
+ * Resets the given cipher context, setting the IV to the specified value.
281
+ * Preserves the associated key information.
282
+ *
283
+ * @param ctx 		Cipher's context. May not be NULL.
284
+ * @param iv_buf	The IV to use.
285
+ *
286
+ * @return 		\c 0 on failure, \c 1 on success.
287
+ */
288
+int cipher_ctx_reset (cipher_ctx_t *ctx, uint8_t *iv_buf);
289
+
290
+/**
291
+ * Updates the given cipher context, encrypting data in the source buffer, and
292
+ * placing any complete blocks in the destination buffer.
293
+ *
294
+ * Note that if a complete block cannot be written, data is cached in the
295
+ * context, and emitted at a later call to \c cipher_ctx_update, or by a call
296
+ * to \c cipher_ctx_final(). This implies that dst should have enough room for
297
+ * src_len + \c cipher_ctx_block_size() - 1.
298
+ *
299
+ * @param ctx 		Cipher's context. May not be NULL.
300
+ * @param dst		Destination buffer
301
+ * @param dst_len	Length of the destination buffer, in bytes
302
+ * @param src		Source buffer
303
+ * @param src_len	Length of the source buffer, in bytes
304
+ *
305
+ * @return 		\c 0 on failure, \c 1 on success.
306
+ */
307
+int cipher_ctx_update (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len,
308
+    uint8_t *src, int src_len);
309
+
310
+/**
311
+ * Pads the final cipher block using PKCS padding, and output to the destination
312
+ * buffer.
313
+ *
314
+ * @param ctx 		Cipher's context. May not be NULL.
315
+ * @param dst		Destination buffer
316
+ * @param dst_len	Length of the destination buffer, in bytes
317
+ *
318
+ * @return 		\c 0 on failure, \c 1 on success.
319
+ */
320
+int cipher_ctx_final (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len);
321
+
222 322
 /*
223 323
  *
224 324
  * Generic message digest information functions
... ...
@@ -560,6 +560,95 @@ cipher_kt_mode (const EVP_CIPHER *cipher_kt)
560 560
   return EVP_CIPHER_mode (cipher_kt);
561 561
 }
562 562
 
563
+/*
564
+ *
565
+ * Generic cipher context functions
566
+ *
567
+ */
568
+
569
+
570
+void
571
+cipher_ctx_init (EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len,
572
+    const EVP_CIPHER *kt, int enc, const char *prefix)
573
+{
574
+  struct gc_arena gc = gc_new ();
575
+
576
+  ASSERT(NULL != kt && NULL != ctx);
577
+
578
+  CLEAR (*ctx);
579
+
580
+  EVP_CIPHER_CTX_init (ctx);
581
+  if (!EVP_CipherInit_ov (ctx, kt, NULL, NULL, enc))
582
+    msg (M_SSLERR, "EVP cipher init #1");
583
+#ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH
584
+  if (!EVP_CIPHER_CTX_set_key_length (ctx, key_len))
585
+    msg (M_SSLERR, "EVP set key size");
586
+#endif
587
+  if (!EVP_CipherInit_ov (ctx, NULL, key, NULL, enc))
588
+    msg (M_SSLERR, "EVP cipher init #2");
589
+
590
+  msg (D_HANDSHAKE, "%s: Cipher '%s' initialized with %d bit key",
591
+      prefix,
592
+      OBJ_nid2sn (EVP_CIPHER_CTX_nid (ctx)),
593
+      EVP_CIPHER_CTX_key_length (ctx) * 8);
594
+
595
+  /* make sure we used a big enough key */
596
+  ASSERT (EVP_CIPHER_CTX_key_length (ctx) <= key_len);
597
+
598
+  dmsg (D_SHOW_KEYS, "%s: CIPHER KEY: %s", prefix,
599
+      format_hex (key, key_len, 0, &gc));
600
+  dmsg (D_CRYPTO_DEBUG, "%s: CIPHER block_size=%d iv_size=%d",
601
+      prefix,
602
+      EVP_CIPHER_CTX_block_size (ctx),
603
+      EVP_CIPHER_CTX_iv_length (ctx));
604
+
605
+  gc_free (&gc);
606
+}
607
+
608
+void
609
+cipher_ctx_cleanup (EVP_CIPHER_CTX *ctx)
610
+{
611
+  EVP_CIPHER_CTX_cleanup (ctx);
612
+}
613
+
614
+int
615
+cipher_ctx_iv_length (const EVP_CIPHER_CTX *ctx)
616
+{
617
+  return EVP_CIPHER_CTX_iv_length (ctx);
618
+}
619
+
620
+int
621
+cipher_ctx_block_size(const EVP_CIPHER_CTX *ctx)
622
+{
623
+  return EVP_CIPHER_CTX_block_size (ctx);
624
+}
625
+
626
+int
627
+cipher_ctx_mode (const EVP_CIPHER_CTX *ctx)
628
+{
629
+  return EVP_CIPHER_CTX_mode (ctx);
630
+}
631
+
632
+int
633
+cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf)
634
+{
635
+  return EVP_CipherInit_ov (ctx, NULL, NULL, iv_buf, -1);
636
+}
637
+
638
+int
639
+cipher_ctx_update (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len,
640
+    uint8_t *src, int src_len)
641
+{
642
+  return EVP_CipherUpdate_ov (ctx, dst, dst_len, src, src_len);
643
+}
644
+
645
+int
646
+cipher_ctx_final (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len)
647
+{
648
+  return EVP_CipherFinal (ctx, dst, dst_len);
649
+}
650
+
651
+
563 652
 void
564 653
 cipher_des_encrypt_ecb (const unsigned char key[8],
565 654
     unsigned char *src,