@@ -219,9 +219,8 @@ ossl_cipher_init(VALUE self, int enc)
219219 *
220220 * Initializes the Cipher for encryption.
221221 *
222- * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
223- * following methods:
224- * * [#key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen]
222+ * Make sure to call either #encrypt or #decrypt before using the Cipher for
223+ * any operation or setting any parameters.
225224 *
226225 * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
227226 */
@@ -237,9 +236,8 @@ ossl_cipher_encrypt(VALUE self)
237236 *
238237 * Initializes the Cipher for decryption.
239238 *
240- * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
241- * following methods:
242- * * [#key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen]
239+ * Make sure to call either #encrypt or #decrypt before using the Cipher for
240+ * any operation or setting any parameters.
243241 *
244242 * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
245243 */
@@ -255,19 +253,15 @@ ossl_cipher_decrypt(VALUE self)
255253 *
256254 * Generates and sets the key/IV based on a password.
257255 *
258- * *WARNING*: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40,
259- * or DES with MD5 or SHA1. Using anything else (like AES) will generate the
260- * key/iv using an OpenSSL specific method. This method is deprecated and
261- * should no longer be used. Use a PKCS5 v2 key generation method from
262- * OpenSSL::PKCS5 instead.
256+ * *WARNING*: This method is deprecated and should not be used. This method
257+ * corresponds to EVP_BytesToKey(), a non-standard OpenSSL extension of the
258+ * legacy PKCS #5 v1.5 key derivation function. See OpenSSL::KDF for other
259+ * options to derive keys from passwords.
263260 *
264261 * === Parameters
265262 * * _salt_ must be an 8 byte string if provided.
266263 * * _iterations_ is an integer with a default of 2048.
267264 * * _digest_ is a Digest object that defaults to 'MD5'
268- *
269- * A minimum of 1000 iterations is recommended.
270- *
271265 */
272266static VALUE
273267ossl_cipher_pkcs5_keyivgen (int argc , VALUE * argv , VALUE self )
@@ -339,6 +333,9 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p
339333 *
340334 * If _buffer_ is given, the encryption/decryption result will be written to
341335 * it. _buffer_ will be resized automatically.
336+ *
337+ * *NOTE*: When decrypting using an AEAD cipher, the integrity of the output
338+ * is not verified until #final has been called.
342339 */
343340static VALUE
344341ossl_cipher_update (int argc , VALUE * argv , VALUE self )
@@ -398,14 +395,17 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
398395 * cipher.final -> string
399396 *
400397 * Returns the remaining data held in the cipher object. Further calls to
401- * Cipher#update or Cipher#final will return garbage . This call should always
398+ * Cipher#update or Cipher#final are invalid . This call should always
402399 * be made as the last call of an encryption or decryption operation, after
403400 * having fed the entire plaintext or ciphertext to the Cipher instance.
404401 *
405- * If an authenticated cipher was used, a CipherError is raised if the tag
406- * could not be authenticated successfully. Only call this method after
407- * setting the authentication tag and passing the entire contents of the
408- * ciphertext into the cipher.
402+ * When encrypting using an AEAD cipher, the authentication tag can be
403+ * retrieved by #auth_tag after #final has been called.
404+ *
405+ * When decrypting using an AEAD cipher, this method will verify the integrity
406+ * of the ciphertext and the associated data with the authentication tag,
407+ * which must be set by #auth_tag= prior to calling this method.
408+ * If the verification fails, CipherError will be raised.
409409 */
410410static VALUE
411411ossl_cipher_final (VALUE self )
@@ -452,14 +452,16 @@ ossl_cipher_name(VALUE self)
452452
453453/*
454454 * call-seq:
455- * cipher.key = string -> string
455+ * cipher.key = string
456456 *
457457 * Sets the cipher key. To generate a key, you should either use a secure
458458 * random byte string or, if the key is to be derived from a password, you
459459 * should rely on PBKDF2 functionality provided by OpenSSL::PKCS5. To
460460 * generate a secure random-based key, Cipher#random_key may be used.
461461 *
462462 * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
463+ *
464+ * See also the man page EVP_CipherInit_ex(3).
463465 */
464466static VALUE
465467ossl_cipher_set_key (VALUE self , VALUE key )
@@ -484,15 +486,21 @@ ossl_cipher_set_key(VALUE self, VALUE key)
484486
485487/*
486488 * call-seq:
487- * cipher.iv = string -> string
489+ * cipher.iv = string
488490 *
489491 * Sets the cipher IV. Please note that since you should never be using ECB
490492 * mode, an IV is always explicitly required and should be set prior to
491- * encryption. The IV itself can be safely transmitted in public, but it
492- * should be unpredictable to prevent certain kinds of attacks. You may use
493- * Cipher#random_iv to create a secure random IV.
493+ * encryption. The IV itself can be safely transmitted in public.
494494 *
495- * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
495+ * This method expects the String to have the length equal to #iv_len. To use
496+ * a different IV length with an AEAD cipher, #iv_len= must be set prior to
497+ * calling this method.
498+ *
499+ * *NOTE*: In OpenSSL API conventions, the IV value may correspond to the
500+ * "nonce" instead in some cipher modes. Refer to the OpenSSL man pages for
501+ * details.
502+ *
503+ * See also the man page EVP_CipherInit_ex(3).
496504 */
497505static VALUE
498506ossl_cipher_set_iv (VALUE self , VALUE iv )
@@ -520,8 +528,7 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
520528 * call-seq:
521529 * cipher.authenticated? -> true | false
522530 *
523- * Indicated whether this Cipher instance uses an Authenticated Encryption
524- * mode.
531+ * Indicates whether this Cipher instance uses an AEAD mode.
525532 */
526533static VALUE
527534ossl_cipher_is_authenticated (VALUE self )
@@ -535,21 +542,23 @@ ossl_cipher_is_authenticated(VALUE self)
535542
536543/*
537544 * call-seq:
538- * cipher.auth_data = string -> string
545+ * cipher.auth_data = string
546+ *
547+ * Sets additional authenticated data (AAD), also called associated data, for
548+ * this Cipher. This method is available for AEAD ciphers.
539549 *
540- * Sets the cipher's additional authenticated data. This field must be
541- * set when using AEAD cipher modes such as GCM or CCM. If no associated
542- * data shall be used, this method must *still* be called with a value of "".
543550 * The contents of this field should be non-sensitive data which will be
544551 * added to the ciphertext to generate the authentication tag which validates
545552 * the contents of the ciphertext.
546553 *
547- * The AAD must be set prior to encryption or decryption. In encryption mode,
548- * it must be set after calling Cipher#encrypt and setting Cipher#key= and
549- * Cipher#iv=. When decrypting, the authenticated data must be set after key,
550- * iv and especially *after* the authentication tag has been set. I.e. set it
551- * only after calling Cipher#decrypt, Cipher#key=, Cipher#iv= and
552- * Cipher#auth_tag= first.
554+ * This method must be called after #key= and #iv= have been set, but before
555+ * starting actual encryption or decryption with #update. In some cipher modes,
556+ * #auth_tag_len= and #ccm_data_len= may also need to be called before this
557+ * method.
558+ *
559+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
560+ * This method internally calls EVP_CipherUpdate() with the output buffer
561+ * set to NULL.
553562 */
554563static VALUE
555564ossl_cipher_set_auth_data (VALUE self , VALUE data )
@@ -577,16 +586,17 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data)
577586 * call-seq:
578587 * cipher.auth_tag(tag_len = 16) -> String
579588 *
580- * Gets the authentication tag generated by Authenticated Encryption Cipher
581- * modes (GCM for example). This tag may be stored along with the ciphertext,
582- * then set on the decryption cipher to authenticate the contents of the
583- * ciphertext against changes. If the optional integer parameter _tag_len_ is
584- * given, the returned tag will be _tag_len_ bytes long. If the parameter is
585- * omitted, the default length of 16 bytes or the length previously set by
586- * #auth_tag_len= will be used. For maximum security, the longest possible
587- * should be chosen.
589+ * Gets the generated authentication tag. This method is available for AEAD
590+ * ciphers, and should be called after encryption has been finalized by calling
591+ * #final.
592+ *
593+ * The returned tag will be _tag_len_ bytes long. Some cipher modes require
594+ * the desired length in advance using a separate call to #auth_tag_len=,
595+ * before starting encryption.
588596 *
589- * The tag may only be retrieved after calling Cipher#final.
597+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
598+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
599+ * EVP_CTRL_AEAD_GET_TAG.
590600 */
591601static VALUE
592602ossl_cipher_get_auth_tag (int argc , VALUE * argv , VALUE self )
@@ -615,16 +625,24 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
615625
616626/*
617627 * call-seq:
618- * cipher.auth_tag = string -> string
628+ * cipher.auth_tag = string
619629 *
620630 * Sets the authentication tag to verify the integrity of the ciphertext.
621- * This can be called only when the cipher supports AE. The tag must be set
622- * after calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before
623- * calling Cipher#final. After all decryption is performed, the tag is
624- * verified automatically in the call to Cipher#final.
625631 *
626- * For OCB mode, the tag length must be supplied with #auth_tag_len=
627- * beforehand.
632+ * The authentication tag must be set before #final is called. The tag is
633+ * verified during the #final call.
634+ *
635+ * Note that, for CCM mode and OCB mode, the expected length of the tag must
636+ * be set before starting decryption by a separate call to #auth_tag_len=.
637+ * The content of the tag can be provided at any time before #final is called.
638+ *
639+ * *NOTE*: The caller must ensure that the String passed to this method has
640+ * the desired length. Some cipher modes support variable tag lengths, and
641+ * this method may accept a truncated tag without raising an exception.
642+ *
643+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
644+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
645+ * EVP_CTRL_AEAD_SET_TAG.
628646 */
629647static VALUE
630648ossl_cipher_set_auth_tag (VALUE self , VALUE vtag )
@@ -649,14 +667,17 @@ ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
649667
650668/*
651669 * call-seq:
652- * cipher.auth_tag_len = Integer -> Integer
670+ * cipher.auth_tag_len = integer
653671 *
654- * Sets the length of the authentication tag to be generated or to be given for
655- * AEAD ciphers that requires it as in input parameter. Note that not all AEAD
656- * ciphers support this method .
672+ * Sets the length of the expected authentication tag for this Cipher. This
673+ * method is available for some of AEAD ciphers that require the length to be
674+ * set before starting encryption or decryption, such as CCM mode or OCB mode .
657675 *
658- * In OCB mode, the length must be supplied both when encrypting and when
659- * decrypting, and must be before specifying an IV.
676+ * For CCM mode and OCB mode, the tag length must be set before #iv= is set.
677+ *
678+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
679+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
680+ * EVP_CTRL_AEAD_SET_TAG and a NULL buffer.
660681 */
661682static VALUE
662683ossl_cipher_set_auth_tag_len (VALUE self , VALUE vlen )
@@ -679,11 +700,16 @@ ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
679700
680701/*
681702 * call-seq:
682- * cipher.iv_len = integer -> integer
703+ * cipher.iv_len = integer
704+ *
705+ * Sets the IV/nonce length for this Cipher. This method is available for AEAD
706+ * ciphers that support variable IV lengths. This method can be called if a
707+ * different IV length than OpenSSL's default is desired, prior to calling
708+ * #iv=.
683709 *
684- * Sets the IV/nonce length of the Cipher. Normally block ciphers don't allow
685- * changing the IV length, but some make use of IV for 'nonce'. You may need
686- * this for interoperability with other applications .
710+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
711+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
712+ * EVP_CTRL_AEAD_SET_IVLEN .
687713 */
688714static VALUE
689715ossl_cipher_set_iv_length (VALUE self , VALUE iv_length )
@@ -709,13 +735,14 @@ ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
709735
710736/*
711737 * call-seq:
712- * cipher.key_len = integer -> integer
738+ * cipher.key_len = integer
713739 *
714740 * Sets the key length of the cipher. If the cipher is a fixed length cipher
715741 * then attempting to set the key length to any value other than the fixed
716742 * value is an error.
717743 *
718- * Under normal circumstances you do not need to call this method (and probably shouldn't).
744+ * Under normal circumstances you do not need to call this method (and
745+ * probably shouldn't).
719746 *
720747 * See EVP_CIPHER_CTX_set_key_length for further information.
721748 */
@@ -732,13 +759,16 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
732759 return key_length ;
733760}
734761
762+ // TODO: Should #padding= take a boolean value instead?
735763/*
736764 * call-seq:
737- * cipher.padding = integer -> integer
765+ * cipher.padding = 1 or 0
738766 *
739- * Enables or disables padding. By default encryption operations are padded using standard block padding and the
740- * padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the
741- * total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur.
767+ * Enables or disables padding. By default encryption operations are padded
768+ * using standard block padding and the padding is checked and removed when
769+ * decrypting. If the pad parameter is zero then no padding is performed, the
770+ * total amount of data encrypted or decrypted must then be a multiple of the
771+ * block size or an error will occur.
742772 *
743773 * See EVP_CIPHER_CTX_set_padding for further information.
744774 */
@@ -809,13 +839,17 @@ ossl_cipher_block_size(VALUE self)
809839
810840/*
811841 * call-seq:
812- * cipher.ccm_data_len = integer -> integer
842+ * cipher.ccm_data_len = integer
813843 *
814- * Sets the length of the plaintext / ciphertext message that will be
815- * processed in CCM mode. Make sure to call this method after #key= and
816- * #iv= have been set, and before #auth_data=.
844+ * Sets the total length of the plaintext / ciphertext message that will be
845+ * processed by #update in CCM mode.
817846 *
818- * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
847+ * Make sure to call this method after #key= and #iv= have been set, and
848+ * before #auth_data= or #update are called.
849+ *
850+ * This method is only available for CCM mode ciphers.
851+ *
852+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
819853 */
820854static VALUE
821855ossl_cipher_set_ccm_data_len (VALUE self , VALUE data_len )
@@ -998,24 +1032,28 @@ Init_ossl_cipher(void)
9981032 * could otherwise be exploited to modify ciphertexts in ways beneficial to
9991033 * potential attackers.
10001034 *
1001- * An associated data is used where there is additional information, such as
1035+ * Associated data, also called additional authenticated data (AAD), is
1036+ * optionally used where there is additional information, such as
10021037 * headers or some metadata, that must be also authenticated but not
1003- * necessarily need to be encrypted. If no associated data is needed for
1004- * encryption and later decryption, the OpenSSL library still requires a
1005- * value to be set - "" may be used in case none is available.
1038+ * necessarily need to be encrypted.
10061039 *
10071040 * An example using the GCM (Galois/Counter Mode). You have 16 bytes _key_,
10081041 * 12 bytes (96 bits) _nonce_ and the associated data _auth_data_. Be sure
10091042 * not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the
10101043 * security guarantees of GCM mode.
10111044 *
1045+ * key = OpenSSL::Random.random_bytes(16)
1046+ * nonce = OpenSSL::Random.random_bytes(12)
1047+ * auth_data = "authenticated but unencrypted data"
1048+ * data = "encrypted data"
1049+ *
10121050 * cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
10131051 * cipher.key = key
10141052 * cipher.iv = nonce
10151053 * cipher.auth_data = auth_data
10161054 *
10171055 * encrypted = cipher.update(data) + cipher.final
1018- * tag = cipher.auth_tag # produces 16 bytes tag by default
1056+ * tag = cipher.auth_tag(16)
10191057 *
10201058 * Now you are the receiver. You know the _key_ and have received _nonce_,
10211059 * _auth_data_, _encrypted_ and _tag_ through an untrusted network. Note
@@ -1028,12 +1066,17 @@ Init_ossl_cipher(void)
10281066 * decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt
10291067 * decipher.key = key
10301068 * decipher.iv = nonce
1031- * decipher.auth_tag = tag
1069+ * decipher.auth_tag = tag # could be called at any time before #final
10321070 * decipher.auth_data = auth_data
10331071 *
10341072 * decrypted = decipher.update(encrypted) + decipher.final
10351073 *
10361074 * puts data == decrypted #=> true
1075+ *
1076+ * Note that other AEAD ciphers may require additional steps, such as
1077+ * setting the expected tag length (#auth_tag_len=) or the total data
1078+ * length (#ccm_data_len=) in advance. Make sure to read the relevant man
1079+ * page for details.
10371080 */
10381081 cCipher = rb_define_class_under (mOSSL , "Cipher" , rb_cObject );
10391082 eCipherError = rb_define_class_under (cCipher , "CipherError" , eOSSLError );
0 commit comments