Merge branch 'master' of git://tinc-vpn.org/tinc into 1.1
[tinc] / src / gcrypt / cipher.c
index 2e8e057..6a2cc5a 100644 (file)
@@ -196,7 +196,13 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
                if(!oneshot)
                        return false;
 
-               size_t reqlen = ((inlen + 1) / cipher->blklen) * cipher->blklen;
+               size_t reqlen = ((inlen + cipher->blklen) / cipher->blklen) * cipher->blklen;
+
+               if(*outlen < reqlen) {
+                       logger(LOG_ERR, "Error while encrypting: not enough room for padding");
+                       return false;
+               }
+
                uint8_t padbyte = reqlen - inlen;
                inlen = reqlen - cipher->blklen;
 
@@ -207,6 +213,9 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
                                pad[i] = padbyte;
        }
        
+       if(oneshot)
+               gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
+
        if((err = gcry_cipher_encrypt(cipher->handle, outdata, *outlen, indata, inlen))) {
                logger(LOG_ERR, "Error while encrypting: %s", gcry_strerror(err));
                return false;
@@ -228,6 +237,9 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
 bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
        gcry_error_t err;
 
+       if(oneshot)
+               gcry_cipher_setiv(cipher->handle, cipher->key + cipher->keylen, cipher->blklen);
+
        if((err = gcry_cipher_decrypt(cipher->handle, outdata, *outlen, indata, inlen))) {
                logger(LOG_ERR, "Error while decrypting: %s", gcry_strerror(err));
                return false;
@@ -239,17 +251,22 @@ bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
 
                uint8_t padbyte = ((uint8_t *)outdata)[inlen - 1];
 
-               if(padbyte == 0 || padbyte > cipher->blklen || padbyte > inlen)
+               if(padbyte == 0 || padbyte > cipher->blklen || padbyte > inlen) {
+                       logger(LOG_ERR, "Error while decrypting: invalid padding");
                        return false;
+               }
 
                size_t origlen = inlen - padbyte;
 
                for(int i = inlen - 1; i >= origlen; i--)
-                       if(((uint8_t *)indata)[i] != padbyte)
+                       if(((uint8_t *)outdata)[i] != padbyte) {
+                               logger(LOG_ERR, "Error while decrypting: invalid padding");
                                return false;
+                       }
 
                *outlen = origlen;
-       }
+       } else
+               *outlen = inlen;
 
        return true;
 }