Option to disable standard block padding with EVP API.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 14 Feb 2001 02:11:52 +0000 (02:11 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 14 Feb 2001 02:11:52 +0000 (02:11 +0000)
Add -nopad option to enc command.

Update docs.

CHANGES
apps/enc.c
crypto/evp/evp.h
crypto/evp/evp_enc.c
crypto/evp/evp_err.c
doc/apps/enc.pod
doc/crypto/EVP_EncryptInit.pod

diff --git a/CHANGES b/CHANGES
index e382faa5320f3c0eb10046220592621fb3662197..81cd6c5a7feba439b0c4a7fd038a66d85e3a5950 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,13 @@
 
  Changes between 0.9.6 and 0.9.7  [xx XXX 2000]
 
+  *) New function EVP_CIPHER_CTX_set_padding() this is used to
+     disable standard block padding (aka PKCS#5 padding) in the EVP
+     API, which was previously mandatory. This means that the data is
+     not padded in any way and so the total length much be a multiple
+     of the block size, otherwise an error occurs.
+     [Steve Henson]
+
   *) Initial (incomplete) OCSP SSL support.
      [Steve Henson]
 
index e53cf3b415cb156e204d46b0c73f7079376f6b14..e3dbbb0e947ddcf2b069489a86aa884b05bbd75a 100644 (file)
@@ -111,6 +111,7 @@ int MAIN(int argc, char **argv)
        unsigned char *buff=NULL,*bufsize=NULL;
        int bsize=BSIZE,verbose=0;
        int ret=1,inl;
+       int nopad = 0;
        unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
        unsigned char salt[PKCS5_SALT_LEN];
        char *str=NULL, *passarg = NULL, *pass = NULL;
@@ -174,6 +175,8 @@ int MAIN(int argc, char **argv)
                        printkey=1;
                else if (strcmp(*argv,"-v") == 0)
                        verbose=1;
+               else if (strcmp(*argv,"-nopad") == 0)
+                       nopad=1;
                else if (strcmp(*argv,"-salt") == 0)
                        nosalt=0;
                else if (strcmp(*argv,"-nosalt") == 0)
@@ -513,6 +516,12 @@ bad:
                if ((benc=BIO_new(BIO_f_cipher())) == NULL)
                        goto end;
                BIO_set_cipher(benc,cipher,key,iv,enc);
+               if (nopad)
+                       {
+                       EVP_CIPHER_CTX *ctx;
+                       BIO_get_cipher_ctx(benc, &ctx);
+                       EVP_CIPHER_CTX_set_padding(ctx, 0);
+                       }
                if (debug)
                        {
                        BIO_set_callback(benc,BIO_debug_callback);
index f00d4cf1fbc2fc2a3c093c2395905672aa900cdb..2b5faed5fffc5131d052b79d6350ce3e9f714ac0 100644 (file)
@@ -373,6 +373,8 @@ struct evp_cipher_st
 #define        EVP_CIPH_CTRL_INIT              0x40
 /* Don't use standard key length function */
 #define        EVP_CIPH_CUSTOM_KEY_LENGTH      0x80
+/* Don't use standard block padding */
+#define        EVP_CIPH_NO_PADDING             0x100
 
 /* ctrl() values */
 
@@ -402,6 +404,7 @@ struct evp_cipher_ctx_st
 
        void *app_data;         /* application stuff */
        int key_len;            /* May change for variable length cipher */
+       unsigned long flags;    /* Various flags */
        union
                {
 #ifndef NO_RC4
@@ -620,6 +623,7 @@ void        ERR_load_EVP_strings(void );
 void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
 int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
 int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
+int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
 int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
 
 #ifndef NO_BIO
@@ -807,6 +811,7 @@ void EVP_PBE_cleanup(void);
 #define EVP_F_EVP_CIPHER_CTX_CTRL                       124
 #define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH             122
 #define EVP_F_EVP_DECRYPTFINAL                          101
+#define EVP_F_EVP_ENCRYPTFINAL                          127
 #define EVP_F_EVP_MD_CTX_COPY                           110
 #define EVP_F_EVP_OPENINIT                              102
 #define EVP_F_EVP_PBE_ALG_ADD                           115
@@ -838,6 +843,7 @@ void EVP_PBE_cleanup(void);
 #define EVP_R_CIPHER_PARAMETER_ERROR                    122
 #define EVP_R_CTRL_NOT_IMPLEMENTED                      132
 #define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED            133
+#define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH                 138
 #define EVP_R_DECODE_ERROR                              114
 #define EVP_R_DIFFERENT_KEY_TYPES                       101
 #define EVP_R_ENCODE_ERROR                              115
index e2687f9879ddf59fc18fc09d4a97b4f622f40ca2..14c8506e80c973e5a62393232353ede9d9c57ba5 100644 (file)
@@ -77,6 +77,7 @@ int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
        if (cipher) {
                ctx->cipher=cipher;
                ctx->key_len = cipher->key_len;
+               ctx->flags = 0;
                if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
                        if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
                                EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR);
@@ -200,6 +201,16 @@ int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
                return 1;
                }
        bl=ctx->buf_len;
+       if (ctx->flags & EVP_CIPH_NO_PADDING)
+               {
+               if(bl)
+                       {
+                       EVPerr(EVP_F_EVP_ENCRYPTFINAL,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+                       return 0;
+                       }
+               *outl = 0;
+               return 1;
+               }
        n=b-bl;
        for (i=bl; i<b; i++)
                ctx->buf[i]=n;
@@ -217,6 +228,9 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
        *outl=0;
        if (inl == 0) return 1;
 
+       if (ctx->flags & EVP_CIPH_NO_PADDING)
+               return EVP_EncryptUpdate(ctx, out, outl, in, inl);
+
        b=ctx->cipher->block_size;
        if (b > 1)
                {
@@ -261,6 +275,16 @@ int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 
        *outl=0;
        b=ctx->cipher->block_size;
+       if (ctx->flags & EVP_CIPH_NO_PADDING)
+               {
+               if(ctx->buf_len)
+                       {
+                       EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
+                       return 0;
+                       }
+               *outl = 0;
+               return 1;
+               }
        if (b > 1)
                {
                if (ctx->buf_len != b)
@@ -319,6 +343,13 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
        return 0;
        }
 
+int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
+       {
+       if (pad) ctx->flags &= ~EVP_CIPH_NO_PADDING;
+       else ctx->flags |= EVP_CIPH_NO_PADDING;
+       return 1;
+       }
+
 int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
 {
        int ret;
index f54314b091726bf6aeed79e1a4859a0805d42be3..7842d99fc270342472dd03ba1c006177857528c3 100644 (file)
@@ -71,6 +71,7 @@ static ERR_STRING_DATA EVP_str_functs[]=
 {ERR_PACK(0,EVP_F_EVP_CIPHER_CTX_CTRL,0),      "EVP_CIPHER_CTX_ctrl"},
 {ERR_PACK(0,EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH,0),    "EVP_CIPHER_CTX_set_key_length"},
 {ERR_PACK(0,EVP_F_EVP_DECRYPTFINAL,0), "EVP_DecryptFinal"},
+{ERR_PACK(0,EVP_F_EVP_ENCRYPTFINAL,0), "EVP_EncryptFinal"},
 {ERR_PACK(0,EVP_F_EVP_MD_CTX_COPY,0),  "EVP_MD_CTX_copy"},
 {ERR_PACK(0,EVP_F_EVP_OPENINIT,0),     "EVP_OpenInit"},
 {ERR_PACK(0,EVP_F_EVP_PBE_ALG_ADD,0),  "EVP_PBE_alg_add"},
@@ -105,6 +106,7 @@ static ERR_STRING_DATA EVP_str_reasons[]=
 {EVP_R_CIPHER_PARAMETER_ERROR            ,"cipher parameter error"},
 {EVP_R_CTRL_NOT_IMPLEMENTED              ,"ctrl not implemented"},
 {EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED    ,"ctrl operation not implemented"},
+{EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH ,"data not multiple of block length"},
 {EVP_R_DECODE_ERROR                      ,"decode error"},
 {EVP_R_DIFFERENT_KEY_TYPES               ,"different key types"},
 {EVP_R_ENCODE_ERROR                      ,"encode error"},
index e436ccc37e6f2fdbf60af914f07188f89c5bd946..9323223cd251f976dc2f654bf41844229f87c361 100644 (file)
@@ -21,6 +21,7 @@ B<openssl enc -ciphername>
 [B<-p>]
 [B<-P>]
 [B<-bufsize number>]
+[B<-nopad>]
 [B<-debug>]
 
 =head1 DESCRIPTION
@@ -116,6 +117,10 @@ or decryption.
 
 set the buffer size for I/O
 
+=item B<-nopad>
+
+disable standard block padding
+
 =item B<-debug>
 
 debug the BIOs used for I/O.
@@ -144,11 +149,14 @@ Some of the ciphers do not have large keys and others have security
 implications if not used correctly. A beginner is advised to just use
 a strong block cipher in CBC mode such as bf or des3.
 
-All the block ciphers use PKCS#5 padding also known as standard block
+All the block ciphers normally use PKCS#5 padding also known as standard block
 padding: this allows a rudimentary integrity or password check to be
 performed. However since the chance of random data passing the test is
 better than 1 in 256 it isn't a very good test.
 
+If padding is disabled then the input data must be a muliple of the cipher
+block length.
+
 All RC2 ciphers have the same key and effective key length.
 
 Blowfish and RC5 algorithms use a 128 bit key.
@@ -250,8 +258,8 @@ The B<-A> option when used with large files doesn't work properly.
 
 There should be an option to allow an iteration count to be included.
 
-Like the EVP library the B<enc> program only supports a fixed number of
-algorithms with certain parameters. So if, for example, you want to use RC2
-with a 76 bit key or RC4 with an 84 bit key you can't use this program.
+The B<enc> program only supports a fixed number of algorithms with
+certain parameters. So if, for example, you want to use RC2 with a
+76 bit key or RC4 with an 84 bit key you can't use this program.
 
 =cut
index 9afe2396e203c822bea78b16a7b69db4ca31b74b..9e8c16eb41cf6fc054cbf6ed9469f3d9a5728d23 100644 (file)
@@ -12,7 +12,7 @@ EVP_CIPHER_mode, EVP_CIPHER_type, EVP_CIPHER_CTX_cipher, EVP_CIPHER_CTX_nid,
 EVP_CIPHER_CTX_block_size, EVP_CIPHER_CTX_key_length, EVP_CIPHER_CTX_iv_length,
 EVP_CIPHER_CTX_get_app_data, EVP_CIPHER_CTX_set_app_data, EVP_CIPHER_CTX_type,
 EVP_CIPHER_CTX_flags, EVP_CIPHER_CTX_mode, EVP_CIPHER_param_to_asn1,
-EVP_CIPHER_asn1_to_param - EVP cipher routines
+EVP_CIPHER_asn1_to_param, EVP_CIPHER_CTX_set_padding - EVP cipher routines
 
 =head1 SYNOPSIS
 
@@ -39,6 +39,7 @@ EVP_CIPHER_asn1_to_param - EVP cipher routines
  int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm,
          int *outl);
 
+ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
  int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
  int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
  int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
@@ -89,22 +90,28 @@ multiple times to encrypt successive blocks of data. The amount
 of data written depends on the block alignment of the encrypted data:
 as a result the amount of data written may be anything from zero bytes
 to (inl + cipher_block_size - 1) so B<outl> should contain sufficient
-room.  The actual number of bytes written is placed in B<outl>.
+room. The actual number of bytes written is placed in B<outl>.
 
-EVP_EncryptFinal() encrypts the "final" data, that is any data that
-remains in a partial block. It uses L<standard block padding|/NOTES> (aka PKCS
-padding). The encrypted final data is written to B<out> which should
-have sufficient space for one cipher block. The number of bytes written
-is placed in B<outl>. After this function is called the encryption operation
-is finished and no further calls to EVP_EncryptUpdate() should be made.
+If padding is enabled (the default) then EVP_EncryptFinal() encrypts
+the "final" data, that is any data that remains in a partial block.
+It uses L<standard block padding|/NOTES> (aka PKCS padding). The encrypted
+final data is written to B<out> which should have sufficient space for
+one cipher block. The number of bytes written is placed in B<outl>. After
+this function is called the encryption operation is finished and no further
+calls to EVP_EncryptUpdate() should be made.
+
+If padding is disabled then EVP_EncryptFinal() will not encrypt any more
+data and it will return an error if any data remains in a partial block:
+that is if the total data length is not a multiple of the block size. 
 
 EVP_DecryptInit(), EVP_DecryptUpdate() and EVP_DecryptFinal() are the
 corresponding decryption operations. EVP_DecryptFinal() will return an
-error code if the final block is not correctly formatted. The parameters
-and restrictions are identical to the encryption operations except that
-the decrypted data buffer B<out> passed to EVP_DecryptUpdate() should
-have sufficient room for (B<inl> + cipher_block_size) bytes unless the
-cipher block size is 1 in which case B<inl> bytes is sufficient.
+error code if padding is enabled and the final block is not correctly
+formatted. The parameters and restrictions are identical to the encryption
+operations except that if padding is enabled the decrypted data buffer B<out>
+passed to EVP_DecryptUpdate() should have sufficient room for
+(B<inl> + cipher_block_size) bytes unless the cipher block size is 1 in
+which case B<inl> bytes is sufficient.
 
 EVP_CipherInit(), EVP_CipherUpdate() and EVP_CipherFinal() are functions
 that can be used for decryption or encryption. The operation performed
@@ -125,6 +132,13 @@ passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX> structure.  The actual NID
 value is an internal value which may not have a corresponding OBJECT
 IDENTIFIER.
 
+EVP_CIPHER_CTX_set_padding() enables or disables padding. By default
+encryption operations are padded using standard block padding and the
+padding is checked and removed when decrypting. If the B<pad> parameter
+is zero then no padding is performed, the total amount of data encrypted
+or decrypted must then be a multiple of the block size or an error will
+occur.
+
 EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key
 length of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
 structure. The constant B<EVP_MAX_KEY_LENGTH> is the maximum key length
@@ -207,6 +221,8 @@ size.
 EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key
 length.
 
+EVP_CIPHER_CTX_set_padding() always returns 1.
+
 EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV
 length or zero if the cipher does not use an IV.
 
@@ -301,10 +317,13 @@ encrypted then 5 padding bytes of value 5 will be added.
 
 When decrypting the final block is checked to see if it has the correct form.
 
-Although the decryption operation can produce an error, it is not a strong
-test that the input data or key is correct. A random block has better than
-1 in 256 chance of being of the correct format and problems with the
-input data earlier on will not produce a final decrypt error.
+Although the decryption operation can produce an error if padding is enabled,
+it is not a strong test that the input data or key is correct. A random block
+has better than 1 in 256 chance of being of the correct format and problems with
+the input data earlier on will not produce a final decrypt error.
+
+If padding is disabled then the decryption operation will always succeed if
+the total amount of data decrypted is a multiple of the block size.
 
 The functions EVP_EncryptInit(), EVP_EncryptUpdate(), EVP_EncryptFinal(),
 EVP_DecryptInit(), EVP_DecryptUpdate(), EVP_CipherInit() and EVP_CipherUpdate()
@@ -318,8 +337,6 @@ and attempt to set the key before the cipher is set in EVP_EncryptInit() ).
 For RC5 the number of rounds can currently only be set to 8, 12 or 16. This is
 a limitation of the current RC5 code rather than the EVP interface.
 
-It should be possible to disable PKCS padding: currently it isn't.
-
 EVP_MAX_KEY_LENGTH and EVP_MAX_IV_LENGTH only refer to the internal ciphers with
 default key lengths. If custom ciphers exceed these values the results are
 unpredictable. This is because it has become standard practice to define a 
@@ -333,22 +350,22 @@ for certain common S/MIME ciphers (RC2, DES, triple DES) in CBC mode.
 Get the number of rounds used in RC5:
 
  int nrounds;
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC5_ROUNDS, 0, &i);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC5_ROUNDS, 0, &nrounds);
 
 Get the RC2 effective key length:
 
  int key_bits;
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC2_KEY_BITS, 0, &key_bits);
 
 Set the number of rounds used in RC5:
 
  int nrounds;
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC5_ROUNDS, i, NULL);
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC5_ROUNDS, nrounds, NULL);
 
-Set the number of rounds used in RC2:
+Set the effective key length used in RC2:
 
- int nrounds;
- EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, i, NULL);
+ int key_bits;
+ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL);
 
 =head1 SEE ALSO