Use IV length of a crypter instead of block size for IV calculations
authorMartin Willi <martin@revosec.ch>
Fri, 13 Aug 2010 10:20:25 +0000 (12:20 +0200)
committerMartin Willi <martin@revosec.ch>
Fri, 13 Aug 2010 15:11:53 +0000 (17:11 +0200)
src/libcharon/encoding/payloads/encryption_payload.c
src/libsimaka/simaka_message.c
src/libstrongswan/crypto/crypto_tester.c
src/libstrongswan/crypto/pkcs7.c
src/libstrongswan/plugins/pem/pem_builder.c
src/libtls/tls_crypto.c
src/libtls/tls_protection.c
src/pluto/demux.c
src/pluto/ipsec_doi.c
src/pluto/pkcs7.c

index 2adbb88..e31b438 100644 (file)
@@ -199,7 +199,7 @@ static void compute_length(private_encryption_payload_t *this)
                block_size = this->crypter->get_block_size(this->crypter);
                length += block_size - length % block_size;
                /* add iv */
-               length += block_size;
+               length += this->crypter->get_iv_size(this->crypter);
                /* add signature */
                length += this->signer->get_block_size(this->signer);
        }
@@ -355,7 +355,7 @@ static status_t encrypt(private_encryption_payload_t *this)
        *(to_crypt.ptr + to_crypt.len - 1) = padding.len;
 
        /* build iv */
-       iv.len = block_size;
+       iv.len = this->crypter->get_iv_size(this->crypter);
        rng->allocate_bytes(rng, iv.len, &iv);
        rng->destroy(rng);
 
@@ -450,17 +450,22 @@ static status_t decrypt(private_encryption_payload_t *this)
        }
 
        /* get IV */
-       iv.len = this->crypter->get_block_size(this->crypter);
-
+       iv.len = this->crypter->get_iv_size(this->crypter);
+       if (iv.len > this->encrypted.len)
+       {
+               DBG1(DBG_ENC, "could not decrypt, input too short");
+               return FAILED;
+       }
        iv.ptr = this->encrypted.ptr;
 
-       /* point concatenated to data + padding + padding_length*/
+       /* point concatenated to data + padding + padding_length */
        concatenated.ptr = this->encrypted.ptr + iv.len;
        concatenated.len = this->encrypted.len - iv.len -
                                                                this->signer->get_block_size(this->signer);
 
        /* concatenated must be a multiple of block_size of crypter */
-       if (concatenated.len < iv.len || concatenated.len % iv.len)
+       if (concatenated.len < iv.len ||
+               concatenated.len % this->crypter->get_block_size(this->crypter))
        {
                DBG1(DBG_ENC, "could not decrypt, invalid input");
                return FAILED;
index e0319e9..3a8f4be 100644 (file)
@@ -741,6 +741,7 @@ static eap_payload_t* generate(private_simaka_message_t *this, chunk_t sigdata)
 
                crypter = this->crypto->get_crypter(this->crypto);
                bs = crypter->get_block_size(crypter);
+               iv.len = crypter->get_iv_size(crypter);
 
                /* add AT_PADDING attribute */
                padding = bs - ((sizeof(encr_buf) - encr.len) % bs);
@@ -757,15 +758,15 @@ static eap_payload_t* generate(private_simaka_message_t *this, chunk_t sigdata)
                /* add IV attribute */
                hdr = (attr_hdr_t*)out.ptr;
                hdr->type = AT_IV;
-               hdr->length = bs / 4 + 1;
+               hdr->length = iv.len / 4 + 1;
                memset(out.ptr + 2, 0, 2);
                out = chunk_skip(out, 4);
 
                rng = this->crypto->get_rng(this->crypto);
-               rng->get_bytes(rng, bs, out.ptr);
+               rng->get_bytes(rng, iv.len, out.ptr);
 
-               iv = chunk_clonea(chunk_create(out.ptr, bs));
-               out = chunk_skip(out, bs);
+               iv = chunk_clonea(chunk_create(out.ptr, iv.len));
+               out = chunk_skip(out, iv.len);
 
                /* inline encryption */
                crypter->encrypt(crypter, encr, iv, NULL);
index 6d3521a..77750cd 100644 (file)
@@ -121,7 +121,7 @@ static bool test_crypter(private_crypto_tester_t *this,
 
                key = chunk_create(vector->key, crypter->get_key_size(crypter));
                crypter->set_key(crypter, key);
-               iv = chunk_create(vector->iv, crypter->get_block_size(crypter));
+               iv = chunk_create(vector->iv, crypter->get_iv_size(crypter));
 
                /* allocated encryption */
                plain = chunk_create(vector->plain, vector->len);
index 81416bc..a4e0b95 100644 (file)
@@ -559,7 +559,7 @@ static bool parse_envelopedData(private_pkcs7_t *this, chunk_t serialNumber,
                                                DBG1(DBG_LIB, "IV could not be parsed");
                                                goto end;
                                        }
-                                       if (iv.len != crypter->get_block_size(crypter))
+                                       if (iv.len != crypter->get_iv_size(crypter))
                                        {
                                                DBG1(DBG_LIB, "IV has wrong length");
                                                goto end;
@@ -752,7 +752,7 @@ bool build_envelopedData(private_pkcs7_t *this, x509_t *cert,
                rng->destroy(rng);
 
                rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
-               rng->allocate_bytes(rng, crypter->get_block_size(crypter), &iv);
+               rng->allocate_bytes(rng, crypter->get_iv_size(crypter), &iv);
                DBG4(DBG_LIB, "  initialization vector: %B", &iv);
                rng->destroy(rng);
        }
index 34527d9..b760add 100644 (file)
@@ -127,8 +127,8 @@ static status_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg,
        }
        crypter->set_key(crypter, key);
 
-       if (iv.len != crypter->get_block_size(crypter) ||
-               blob->len % iv.len)
+       if (iv.len != crypter->get_iv_size(crypter) ||
+               blob->len % crypter->get_block_size(crypter))
        {
                crypter->destroy(crypter);
                DBG1(DBG_LIB, "  data size is not multiple of block size");
index b8eb87b..5668f13 100644 (file)
@@ -772,7 +772,7 @@ METHOD(tls_crypto_t, derive_secrets, void,
                eks = this->crypter_out->get_key_size(this->crypter_out);
                if (this->tls->get_version(this->tls) < TLS_1_1)
                {
-                       ivs = this->crypter_out->get_block_size(this->crypter_out);
+                       ivs = this->crypter_out->get_iv_size(this->crypter_out);
                }
        }
        seed = chunk_cata("cc", server_random, client_random);
index 51a4808..107751e 100644 (file)
@@ -112,23 +112,24 @@ METHOD(tls_protection_t, process, status_t,
                u_int8_t bs, padding_length;
 
                bs = this->crypter_in->get_block_size(this->crypter_in);
-               if (data.len < bs || data.len % bs)
-               {
-                       DBG1(DBG_IKE, "encrypted TLS record not multiple of block size");
-                       return FAILED;
-               }
                if (this->iv_in.len)
                {       /* < TLSv1.1 uses IV from key derivation/last block */
+                       if (data.len < bs || data.len % bs)
+                       {
+                               DBG1(DBG_IKE, "encrypted TLS record length invalid");
+                               return FAILED;
+                       }
                        iv = this->iv_in;
                        next_iv = chunk_clone(chunk_create(data.ptr + data.len - bs, bs));
                }
                else
                {       /* TLSv1.1 uses random IVs, prepended to record */
-                       iv = chunk_create(data.ptr, bs);
-                       data = chunk_skip(data, bs);
-                       if (data.len < bs)
+                       iv.len = this->crypter_in->get_iv_size(this->crypter_in);
+                       iv = chunk_create(data.ptr, iv.len);
+                       data = chunk_skip(data, iv.len);
+                       if (data.len < bs || data.len % bs)
                        {
-                               DBG1(DBG_IKE, "TLS record too short to decrypt");
+                               DBG1(DBG_IKE, "encrypted TLS record length invalid");
                                return FAILED;
                        }
                }
@@ -231,7 +232,8 @@ METHOD(tls_protection_t, build, status_t,
                                                free(data->ptr);
                                                return FAILED;
                                        }
-                                       this->rng->allocate_bytes(this->rng, bs, &iv);
+                                       iv.len = this->crypter_out->get_iv_size(this->crypter_out);
+                                       this->rng->allocate_bytes(this->rng, iv.len, &iv);
                                }
 
                                *data = chunk_cat("mmcc", *data, mac, padding,
index 617353c..bdd05c5 100644 (file)
@@ -1782,7 +1782,7 @@ process_packet(struct msg_digest **mdp)
                 * the last phase 1 block, not the last block sent.
                 */
                {
-                       size_t crypter_block_size;
+                       size_t crypter_block_size, crypter_iv_size;
                        encryption_algorithm_t enc_alg;
                        crypter_t *crypter;
                        chunk_t data, iv;
@@ -1791,6 +1791,7 @@ process_packet(struct msg_digest **mdp)
                        enc_alg = oakley_to_encryption_algorithm(st->st_oakley.encrypt);
                        crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, st->st_enc_key.len);
                        crypter_block_size = crypter->get_block_size(crypter);
+                       crypter_iv_size = crypter->get_iv_size(crypter);
 
                        if (pbs_left(&md->message_pbs) % crypter_block_size != 0)
                        {
@@ -1817,17 +1818,17 @@ process_packet(struct msg_digest **mdp)
                        }
 
                        /* form iv by truncation */
-                       st->st_new_iv_len = crypter_block_size;
+                       st->st_new_iv_len = crypter_iv_size;
                        iv = chunk_create(st->st_new_iv, st->st_new_iv_len);
-                       new_iv = alloca(crypter_block_size);
-                       memcpy(new_iv, data.ptr + data.len - crypter_block_size,
-                                  crypter_block_size);
+                       new_iv = alloca(crypter_iv_size);
+                       memcpy(new_iv, data.ptr + data.len - crypter_iv_size,
+                                  crypter_iv_size);
 
                        crypter->set_key(crypter, st->st_enc_key);
                        crypter->decrypt(crypter, data, iv, NULL);
                        crypter->destroy(crypter);
 
-               memcpy(st->st_new_iv, new_iv, crypter_block_size);
+                       memcpy(st->st_new_iv, new_iv, crypter_iv_size);
                        if (restore_iv)
                        {
                                memcpy(st->st_new_iv, new_iv, new_iv_len);
index 4a6a7c8..7ec547b 100644 (file)
@@ -1753,7 +1753,7 @@ bool encrypt_message(pb_stream *pbs, struct state *st)
        size_t enc_len = pbs_offset(pbs) - sizeof(struct isakmp_hdr);
        chunk_t data, iv;
     char *new_iv;
-       size_t crypter_block_size;
+       size_t crypter_block_size, crypter_iv_size;
        encryption_algorithm_t enc_alg;
        crypter_t *crypter;
 
@@ -1761,6 +1761,7 @@ bool encrypt_message(pb_stream *pbs, struct state *st)
        enc_alg = oakley_to_encryption_algorithm(st->st_oakley.encrypt);
        crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, st->st_enc_key.len);
        crypter_block_size = crypter->get_block_size(crypter);
+       crypter_iv_size = crypter->get_iv_size(crypter);
 
        /* Pad up to multiple of encryption blocksize.
         * See the description associated with the definition of
@@ -1781,15 +1782,15 @@ bool encrypt_message(pb_stream *pbs, struct state *st)
        data = chunk_create(enc_start, enc_len);
 
        /* form iv by truncation */
-       st->st_new_iv_len = crypter_block_size;
+       st->st_new_iv_len = crypter_iv_size;
        iv = chunk_create(st->st_new_iv, st->st_new_iv_len);
 
        crypter->set_key(crypter, st->st_enc_key);
        crypter->encrypt(crypter, data, iv, NULL);
        crypter->destroy(crypter);
 
-       new_iv = data.ptr + data.len - crypter_block_size;
-       memcpy(st->st_new_iv, new_iv, crypter_block_size);
+       new_iv = data.ptr + data.len - crypter_iv_size;
+       memcpy(st->st_new_iv, new_iv, crypter_iv_size);
        update_iv(st);
        DBG_cond_dump(DBG_CRYPT, "next IV:", st->st_iv, st->st_iv_len);
        close_message(pbs);
index 9389178..10b2a4d 100644 (file)
@@ -473,7 +473,7 @@ end:
                        DBG1(DBG_LIB, "symmetric key length %d is wrong", symmetric_key.len);
                        goto failed;
                }
-               if (iv.len != crypter->get_block_size(crypter))
+               if (iv.len != crypter->get_iv_size(crypter))
                {
                        DBG1(DBG_LIB, "IV length %d is wrong", iv.len);
                        goto failed;
@@ -668,7 +668,7 @@ chunk_t pkcs7_build_envelopedData(chunk_t data, certificate_t *cert, int enc_alg
                rng->destroy(rng);
 
                rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
-               rng->allocate_bytes(rng, crypter->get_block_size(crypter), &iv);
+               rng->allocate_bytes(rng, crypter->get_iv_size(crypter), &iv);
                DBG4(DBG_LIB, "initialization vector: %B", &iv);
                rng->destroy(rng);
        }