[前][次][番号順一覧][スレッド一覧]

ruby-changes:43314

From: rhe <ko1@a...>
Date: Sun, 12 Jun 2016 14:06:22 +0900 (JST)
Subject: [ruby-changes:43314] rhe:r55388 (trunk): openssl: support non AES-GCM AEAD ciphers in OpenSSL::Cipher

rhe	2016-06-12 14:06:18 +0900 (Sun, 12 Jun 2016)

  New Revision: 55388

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55388

  Log:
    openssl: support non AES-GCM AEAD ciphers in OpenSSL::Cipher
    
    * ext/openssl/ossl_cipher.c (ossl_cipher_get_auth_tag,
      ossl_cipher_set_auth_tag): Check if the cipher flags retrieved by
      EVP_CIPHER_CTX_flags() includes EVP_CIPH_FLAG_AEAD_CIPHER to see if
      the cipher supports AEAD. AES-GCM was the only supported in OpenSSL
      1.0.1.
    
      (Init_ossl_cipher): Fix doc; OpenSSL::Cipher::AES.new(128, :GCM) can't
      work.
    
    * ext/openssl/openssl_missing.h: Define EVP_CTRL_AEAD_{GET,SET}_TAG if
      missing. They are added in OpenSSL 1.1.0, and have the same value as
      EVP_CTRL_GCM_{GET,SET}_TAG and EVP_CTRL_CCM_{GET,SET}_TAG.

  Modified files:
    trunk/ChangeLog
    trunk/ext/openssl/openssl_missing.h
    trunk/ext/openssl/ossl_cipher.c
Index: ext/openssl/ossl_cipher.c
===================================================================
--- ext/openssl/ossl_cipher.c	(revision 55387)
+++ ext/openssl/ossl_cipher.c	(revision 55388)
@@ -553,29 +553,9 @@ ossl_cipher_set_auth_data(VALUE self, VA https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_cipher.c#L553
     return data;
 }
 
-#define ossl_is_gcm(nid)	(nid) == NID_aes_128_gcm || \
-				(nid) == NID_aes_192_gcm || \
-				(nid) == NID_aes_256_gcm
-
-static VALUE
-ossl_get_gcm_auth_tag(EVP_CIPHER_CTX *ctx, int len)
-{
-    unsigned char *tag;
-    VALUE ret;
-
-    tag = ALLOC_N(unsigned char, len);
-
-    if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, len, tag))
-        ossl_raise(eCipherError, "retrieving the authentication tag failed");
-
-    ret = rb_str_new((const char *) tag, len);
-    xfree(tag);
-    return ret;
-}
-
 /*
  *  call-seq:
- *     cipher.auth_tag([ tag_len ] -> string
+ *     cipher.auth_tag(tag_len = 16) -> String
  *
  *  Gets the authentication tag generated by Authenticated Encryption Cipher
  *  modes (GCM for example). This tag may be stored along with the ciphertext,
@@ -590,32 +570,23 @@ ossl_get_gcm_auth_tag(EVP_CIPHER_CTX *ct https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_cipher.c#L570
 static VALUE
 ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
 {
-    VALUE vtag_len;
+    VALUE vtag_len, ret;
     EVP_CIPHER_CTX *ctx;
-    int nid, tag_len;
+    int tag_len = 16;
 
-    if (rb_scan_args(argc, argv, "01", &vtag_len) == 0) {
-	tag_len = 16;
-    } else {
+    if (rb_scan_args(argc, argv, "01", &vtag_len) == 1)
 	tag_len = NUM2INT(vtag_len);
-    }
 
     GetCipher(self, ctx);
-    nid = EVP_CIPHER_CTX_nid(ctx);
 
-    if (ossl_is_gcm(nid)) {
-	return ossl_get_gcm_auth_tag(ctx, tag_len);
-    } else {
+    if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
 	ossl_raise(eCipherError, "authentication tag not supported by this cipher");
-	return Qnil; /* dummy */
-    }
-}
 
-static inline void
-ossl_set_gcm_auth_tag(EVP_CIPHER_CTX *ctx, unsigned char *tag, int tag_len)
-{
-    if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len, tag))
-        ossl_raise(eCipherError, "unable to set GCM tag");
+    ret = rb_str_new(NULL, tag_len);
+    if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, RSTRING_PTR(ret)))
+	ossl_raise(eCipherError, "retrieving the authentication tag failed");
+
+    return ret;
 }
 
 /*
@@ -634,7 +605,6 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_cipher.c#L605
 ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
 {
     EVP_CIPHER_CTX *ctx;
-    int nid;
     unsigned char *tag;
     int tag_len;
 
@@ -643,13 +613,11 @@ ossl_cipher_set_auth_tag(VALUE self, VAL https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_cipher.c#L613
     tag_len = RSTRING_LENINT(vtag);
 
     GetCipher(self, ctx);
-    nid = EVP_CIPHER_CTX_nid(ctx);
-
-    if (ossl_is_gcm(nid)) {
-	ossl_set_gcm_auth_tag(ctx, tag, tag_len);
-    } else {
+    if (!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER))
 	ossl_raise(eCipherError, "authentication tag not supported by this cipher");
-    }
+
+    if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag))
+	ossl_raise(eCipherError, "unable to set AEAD tag");
 
     return vtag;
 }
@@ -665,16 +633,10 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_cipher.c#L633
 ossl_cipher_is_authenticated(VALUE self)
 {
     EVP_CIPHER_CTX *ctx;
-    int nid;
 
     GetCipher(self, ctx);
-    nid = EVP_CIPHER_CTX_nid(ctx);
 
-    if (ossl_is_gcm(nid)) {
-	return Qtrue;
-    } else {
-	return Qfalse;
-    }
+    return (EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_FLAG_AEAD_CIPHER) ? Qtrue : Qfalse;
 }
 #else
 #define ossl_cipher_set_auth_data rb_f_notimplement
@@ -948,7 +910,7 @@ Init_ossl_cipher(void) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_cipher.c#L910
      * the OpenSSL library still requires a value to be set - "" may be used in
      * case none is available. An example using the GCM (Galois Counter Mode):
      *
-     *   cipher = OpenSSL::Cipher::AES.new(128, :GCM)
+     *   cipher = OpenSSL::Cipher.new("aes-128-gcm")
      *   cipher.encrypt
      *   key = cipher.random_key
      *   iv = cipher.random_iv
@@ -957,7 +919,7 @@ Init_ossl_cipher(void) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_cipher.c#L919
      *   encrypted = cipher.update(data) + cipher.final
      *   tag = cipher.auth_tag
      *
-     *   decipher = OpenSSL::Cipher::AES.new(128, :GCM)
+     *   decipher = OpenSSL::Cipher.new("aes-128-gcm")
      *   decipher.decrypt
      *   decipher.key = key
      *   decipher.iv = iv
Index: ext/openssl/openssl_missing.h
===================================================================
--- ext/openssl/openssl_missing.h	(revision 55387)
+++ ext/openssl/openssl_missing.h	(revision 55388)
@@ -228,4 +228,9 @@ IMPL_PKEY_GETTER(EC_KEY, ec) https://github.com/ruby/ruby/blob/trunk/ext/openssl/openssl_missing.h#L228
 #undef IMPL_KEY_ACCESSOR3
 #endif /* HAVE_OPAQUE_OPENSSL */
 
+#if defined(HAVE_AUTHENTICATED_ENCRYPTION) && !defined(EVP_CTRL_AEAD_GET_TAG)
+#  define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
+#  define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
+#endif
+
 #endif /* _OSSL_OPENSSL_MISSING_H_ */
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 55387)
+++ ChangeLog	(revision 55388)
@@ -1,3 +1,18 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Jun 12 14:05:45 2016  Kazuki Yamaguchi  <k@r...>
+
+	* ext/openssl/ossl_cipher.c (ossl_cipher_get_auth_tag,
+	  ossl_cipher_set_auth_tag): Check if the cipher flags retrieved by
+	  EVP_CIPHER_CTX_flags() includes EVP_CIPH_FLAG_AEAD_CIPHER to see if
+	  the cipher supports AEAD. AES-GCM was the only supported in OpenSSL
+	  1.0.1.
+
+	  (Init_ossl_cipher): Fix doc; OpenSSL::Cipher::AES.new(128, :GCM) can't
+	  work.
+
+	* ext/openssl/openssl_missing.h: Define EVP_CTRL_AEAD_{GET,SET}_TAG if
+	  missing. They are added in OpenSSL 1.1.0, and have the same value as
+	  EVP_CTRL_GCM_{GET,SET}_TAG and EVP_CTRL_CCM_{GET,SET}_TAG.
+
 Sun Jun 12 13:47:42 2016  Kazuki Yamaguchi  <k@r...>
 
 	* test/openssl/test_engine.rb (test_openssl_engine_builtin,

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]