From f2e5ca84d4d218a29e2c960d9b23a40d8236cd06 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 14 Feb 2001 02:11:52 +0000 Subject: [PATCH] Option to disable standard block padding with EVP API. Add -nopad option to enc command. Update docs. --- CHANGES | 7 ++++ apps/enc.c | 9 +++++ crypto/evp/evp.h | 6 +++ crypto/evp/evp_enc.c | 31 ++++++++++++++++ crypto/evp/evp_err.c | 2 + doc/apps/enc.pod | 16 ++++++-- doc/crypto/EVP_EncryptInit.pod | 67 +++++++++++++++++++++------------- 7 files changed, 109 insertions(+), 29 deletions(-) diff --git a/CHANGES b/CHANGES index e382faa532..81cd6c5a7f 100644 --- 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] diff --git a/apps/enc.c b/apps/enc.c index e53cf3b415..e3dbbb0e94 100644 --- a/apps/enc.c +++ b/apps/enc.c @@ -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); diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index f00d4cf1fb..2b5faed5ff 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -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 diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index e2687f9879..14c8506e80 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -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; ibuf[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; diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index f54314b091..7842d99fc2 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -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"}, diff --git a/doc/apps/enc.pod b/doc/apps/enc.pod index e436ccc37e..9323223cd2 100644 --- a/doc/apps/enc.pod +++ b/doc/apps/enc.pod @@ -21,6 +21,7 @@ B [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 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 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 diff --git a/doc/crypto/EVP_EncryptInit.pod b/doc/crypto/EVP_EncryptInit.pod index 9afe2396e2..9e8c16eb41 100644 --- a/doc/crypto/EVP_EncryptInit.pod +++ b/doc/crypto/EVP_EncryptInit.pod @@ -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 should contain sufficient -room. The actual number of bytes written is placed in B. +room. The actual number of bytes written is placed in B. -EVP_EncryptFinal() encrypts the "final" data, that is any data that -remains in a partial block. It uses L (aka PKCS -padding). The encrypted final data is written to B which should -have sufficient space for one cipher block. The number of bytes written -is placed in B. 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 (aka PKCS padding). The encrypted +final data is written to B which should have sufficient space for +one cipher block. The number of bytes written is placed in B. 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 passed to EVP_DecryptUpdate() should -have sufficient room for (B + cipher_block_size) bytes unless the -cipher block size is 1 in which case B 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 +passed to EVP_DecryptUpdate() should have sufficient room for +(B + cipher_block_size) bytes unless the cipher block size is 1 in +which case B 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 or B 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 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 or B structure. The constant B 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 -- 2.34.1