浏览代码

replace literals for iv_len/mac_len

Thomas Waldmann 8 年之前
父节点
当前提交
ce5c5781aa
共有 1 个文件被更改,包括 52 次插入38 次删除
  1. 52 38
      src/borg/crypto/low_level.pyx

+ 52 - 38
src/borg/crypto/low_level.pyx

@@ -196,13 +196,18 @@ cdef class AES256_CTR_HMAC_SHA256:
     cdef HMAC_CTX *hmac_ctx
     cdef HMAC_CTX *hmac_ctx
     cdef unsigned char *mac_key
     cdef unsigned char *mac_key
     cdef unsigned char *enc_key
     cdef unsigned char *enc_key
-    cdef unsigned char iv[16]
+    cdef int iv_len, iv_len_short
+    cdef int mac_len
+    cdef unsigned char iv[16]  # XXX use self.iv_len or some MAX_IV_LEN?
     cdef long long blocks
     cdef long long blocks
 
 
     def __init__(self, mac_key, enc_key, iv=None):
     def __init__(self, mac_key, enc_key, iv=None):
         assert isinstance(mac_key, bytes) and len(mac_key) == 32
         assert isinstance(mac_key, bytes) and len(mac_key) == 32
         assert isinstance(enc_key, bytes) and len(enc_key) == 32
         assert isinstance(enc_key, bytes) and len(enc_key) == 32
-        assert iv is None or isinstance(iv, bytes) and len(iv) == 16
+        self.iv_len = 16
+        self.iv_len_short = 8
+        self.mac_len = 32
+        assert iv is None or isinstance(iv, bytes) and len(iv) == self.iv_len
         self.mac_key = mac_key
         self.mac_key = mac_key
         self.enc_key = enc_key
         self.enc_key = enc_key
         if iv is not None:
         if iv is not None:
@@ -225,7 +230,7 @@ cdef class AES256_CTR_HMAC_SHA256:
         cdef int hlen = len(header)
         cdef int hlen = len(header)
         cdef int aoffset = aad_offset
         cdef int aoffset = aad_offset
         cdef int alen = hlen - aoffset
         cdef int alen = hlen - aoffset
-        cdef unsigned char *odata = <unsigned char *>PyMem_Malloc(hlen + 32 + 8 + ilen + 16)
+        cdef unsigned char *odata = <unsigned char *>PyMem_Malloc(hlen + self.mac_len + self.iv_len_short + ilen + 16)
         if not odata:
         if not odata:
             raise MemoryError
             raise MemoryError
         cdef int olen
         cdef int olen
@@ -237,9 +242,9 @@ cdef class AES256_CTR_HMAC_SHA256:
             for i in range(hlen):
             for i in range(hlen):
                 odata[offset+i] = header[i]
                 odata[offset+i] = header[i]
             offset += hlen
             offset += hlen
-            offset += 32
+            offset += self.mac_len
             self.store_iv(odata+offset, self.iv)
             self.store_iv(odata+offset, self.iv)
-            offset += 8
+            offset += self.iv_len_short
             rc = EVP_EncryptInit_ex(self.ctx, EVP_aes_256_ctr(), NULL, self.enc_key, self.iv)
             rc = EVP_EncryptInit_ex(self.ctx, EVP_aes_256_ctr(), NULL, self.enc_key, self.iv)
             if not rc:
             if not rc:
                 raise CryptoError('EVP_EncryptInit_ex failed')
                 raise CryptoError('EVP_EncryptInit_ex failed')
@@ -251,11 +256,11 @@ cdef class AES256_CTR_HMAC_SHA256:
             if not rc:
             if not rc:
                 raise CryptoError('EVP_EncryptFinal_ex failed')
                 raise CryptoError('EVP_EncryptFinal_ex failed')
             offset += olen
             offset += olen
-            if not HMAC_Init_ex(self.hmac_ctx, self.mac_key, 32, EVP_sha256(), NULL):
+            if not HMAC_Init_ex(self.hmac_ctx, self.mac_key, self.mac_len, EVP_sha256(), NULL):
                 raise CryptoError('HMAC_Init_ex failed')
                 raise CryptoError('HMAC_Init_ex failed')
             if not HMAC_Update(self.hmac_ctx, <const unsigned char *> hdata.buf+aoffset, alen):
             if not HMAC_Update(self.hmac_ctx, <const unsigned char *> hdata.buf+aoffset, alen):
                 raise CryptoError('HMAC_Update failed')
                 raise CryptoError('HMAC_Update failed')
-            if not HMAC_Update(self.hmac_ctx, odata+hlen+32, offset-hlen-32):
+            if not HMAC_Update(self.hmac_ctx, odata+hlen+self.mac_len, offset-hlen-self.mac_len):
                 raise CryptoError('HMAC_Update failed')
                 raise CryptoError('HMAC_Update failed')
             if not HMAC_Final(self.hmac_ctx, odata+hlen, NULL):
             if not HMAC_Final(self.hmac_ctx, odata+hlen, NULL):
                 raise CryptoError('HMAC_Final failed')
                 raise CryptoError('HMAC_Final failed')
@@ -279,25 +284,27 @@ cdef class AES256_CTR_HMAC_SHA256:
             raise MemoryError
             raise MemoryError
         cdef int olen
         cdef int olen
         cdef int offset
         cdef int offset
-        cdef unsigned char hmac_buf[32]
+        cdef unsigned char hmac_buf[32]  # XXX use self.mac_len or some MAX_HMAC_LEN?
         cdef Py_buffer idata = ro_buffer(envelope)
         cdef Py_buffer idata = ro_buffer(envelope)
         try:
         try:
-            if not HMAC_Init_ex(self.hmac_ctx, self.mac_key, 32, EVP_sha256(), NULL):
+            if not HMAC_Init_ex(self.hmac_ctx, self.mac_key, self.mac_len, EVP_sha256(), NULL):
                 raise CryptoError('HMAC_Init_ex failed')
                 raise CryptoError('HMAC_Init_ex failed')
             if not HMAC_Update(self.hmac_ctx, <const unsigned char *> idata.buf+aoffset, alen):
             if not HMAC_Update(self.hmac_ctx, <const unsigned char *> idata.buf+aoffset, alen):
                 raise CryptoError('HMAC_Update failed')
                 raise CryptoError('HMAC_Update failed')
-            if not HMAC_Update(self.hmac_ctx, <const unsigned char *> idata.buf+hlen+32, ilen-hlen-32):
+            if not HMAC_Update(self.hmac_ctx, <const unsigned char *> idata.buf+hlen+self.mac_len, ilen-hlen-self.mac_len):
                 raise CryptoError('HMAC_Update failed')
                 raise CryptoError('HMAC_Update failed')
             if not HMAC_Final(self.hmac_ctx, hmac_buf, NULL):
             if not HMAC_Final(self.hmac_ctx, hmac_buf, NULL):
                 raise CryptoError('HMAC_Final failed')
                 raise CryptoError('HMAC_Final failed')
-            if CRYPTO_memcmp(hmac_buf, idata.buf+hlen, 32):
+            if CRYPTO_memcmp(hmac_buf, idata.buf+hlen, self.mac_len):
                 raise IntegrityError('HMAC Authentication failed')
                 raise IntegrityError('HMAC Authentication failed')
-            iv = self.fetch_iv(<unsigned char *> idata.buf+hlen+32)
+            iv = self.fetch_iv(<unsigned char *> idata.buf+hlen+self.mac_len)
             self.set_iv(iv)
             self.set_iv(iv)
             if not EVP_DecryptInit_ex(self.ctx, EVP_aes_256_ctr(), NULL, self.enc_key, iv):
             if not EVP_DecryptInit_ex(self.ctx, EVP_aes_256_ctr(), NULL, self.enc_key, iv):
                 raise CryptoError('EVP_DecryptInit_ex failed')
                 raise CryptoError('EVP_DecryptInit_ex failed')
             offset = 0
             offset = 0
-            rc = EVP_DecryptUpdate(self.ctx, odata+offset, &olen, <const unsigned char*> idata.buf+hlen+32+8, ilen-hlen-32-8)
+            rc = EVP_DecryptUpdate(self.ctx, odata+offset, &olen,
+                                   <const unsigned char*> idata.buf+hlen+self.mac_len+self.iv_len_short,
+                                   ilen-hlen-self.mac_len-self.iv_len_short)
             if not rc:
             if not rc:
                 raise CryptoError('EVP_DecryptUpdate failed')
                 raise CryptoError('EVP_DecryptUpdate failed')
             offset += olen
             offset += olen
@@ -313,21 +320,21 @@ cdef class AES256_CTR_HMAC_SHA256:
 
 
     def set_iv(self, iv):
     def set_iv(self, iv):
         self.blocks = 0  # how many AES blocks got encrypted with this IV?
         self.blocks = 0  # how many AES blocks got encrypted with this IV?
-        for i in range(16):
+        for i in range(self.iv_len):
             self.iv[i] = iv[i]
             self.iv[i] = iv[i]
 
 
     def next_iv(self):
     def next_iv(self):
-        return increment_iv(self.iv[:16], self.blocks)
+        return increment_iv(self.iv[:self.iv_len], self.blocks)
 
 
     cdef fetch_iv(self, unsigned char * iv_in):
     cdef fetch_iv(self, unsigned char * iv_in):
-        # fetch lower 8 bytes of iv and add upper 8 zero bytes
-        return b"\0" * 8 + iv_in[0:8]
+        # fetch lower self.iv_len_short bytes of iv and add upper zero bytes
+        return b'\0' * (self.iv_len - self.iv_len_short) + iv_in[0:self.iv_len_short]
 
 
     cdef store_iv(self, unsigned char * iv_out, unsigned char * iv):
     cdef store_iv(self, unsigned char * iv_out, unsigned char * iv):
-        # store only lower 8 bytes, upper 8 bytes are assumed to be 0
+        # store only lower self.iv_len_short bytes, upper bytes are assumed to be 0
         cdef int i
         cdef int i
-        for i in range(8):
-            iv_out[i] = iv[8+i]
+        for i in range(self.iv_len_short):
+            iv_out[i] = iv[(self.iv_len-self.iv_len_short)+i]
 
 
 
 
 ctypedef const EVP_CIPHER * (* CIPHER)()
 ctypedef const EVP_CIPHER * (* CIPHER)()
@@ -339,13 +346,17 @@ cdef class _AEAD_BASE:
     cdef CIPHER cipher
     cdef CIPHER cipher
     cdef EVP_CIPHER_CTX *ctx
     cdef EVP_CIPHER_CTX *ctx
     cdef unsigned char *enc_key
     cdef unsigned char *enc_key
-    cdef unsigned char iv[12]
+    cdef int iv_len
+    cdef int mac_len
+    cdef unsigned char iv[12]  # XXX use self.iv_len or some MAX_IV_LEN?
     cdef long long blocks
     cdef long long blocks
 
 
     def __init__(self, mac_key, enc_key, iv=None):
     def __init__(self, mac_key, enc_key, iv=None):
         assert mac_key is None
         assert mac_key is None
         assert isinstance(enc_key, bytes) and len(enc_key) == 32
         assert isinstance(enc_key, bytes) and len(enc_key) == 32
-        assert iv is None or isinstance(iv, bytes) and len(iv) == 12
+        self.iv_len = 12
+        self.mac_len = 16
+        assert iv is None or isinstance(iv, bytes) and len(iv) == self.iv_len
         self.enc_key = enc_key
         self.enc_key = enc_key
         if iv is not None:
         if iv is not None:
             self.set_iv(iv)
             self.set_iv(iv)
@@ -365,7 +376,7 @@ cdef class _AEAD_BASE:
         cdef int hlen = len(header)
         cdef int hlen = len(header)
         cdef int aoffset = aad_offset
         cdef int aoffset = aad_offset
         cdef int alen = hlen - aoffset
         cdef int alen = hlen - aoffset
-        cdef unsigned char *odata = <unsigned char *>PyMem_Malloc(hlen + 16 + 12 + ilen + 16)
+        cdef unsigned char *odata = <unsigned char *>PyMem_Malloc(hlen + self.mac_len + self.iv_len + ilen + 16)
         if not odata:
         if not odata:
             raise MemoryError
             raise MemoryError
         cdef int olen
         cdef int olen
@@ -377,12 +388,12 @@ cdef class _AEAD_BASE:
             for i in range(hlen):
             for i in range(hlen):
                 odata[offset+i] = header[i]
                 odata[offset+i] = header[i]
             offset += hlen
             offset += hlen
-            offset += 16
+            offset += self.mac_len
             self.store_iv(odata+offset, self.iv)
             self.store_iv(odata+offset, self.iv)
             rc = EVP_EncryptInit_ex(self.ctx, self.cipher(), NULL, NULL, NULL)
             rc = EVP_EncryptInit_ex(self.ctx, self.cipher(), NULL, NULL, NULL)
             if not rc:
             if not rc:
                 raise CryptoError('EVP_EncryptInit_ex failed')
                 raise CryptoError('EVP_EncryptInit_ex failed')
-            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL):
+            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_SET_IVLEN, self.iv_len, NULL):
                 raise CryptoError('EVP_CIPHER_CTX_ctrl SET IVLEN failed')
                 raise CryptoError('EVP_CIPHER_CTX_ctrl SET IVLEN failed')
             rc = EVP_EncryptInit_ex(self.ctx, NULL, NULL, self.enc_key, self.iv)
             rc = EVP_EncryptInit_ex(self.ctx, NULL, NULL, self.enc_key, self.iv)
             if not rc:
             if not rc:
@@ -390,9 +401,9 @@ cdef class _AEAD_BASE:
             rc = EVP_EncryptUpdate(self.ctx, NULL, &olen, <const unsigned char*> hdata.buf+aoffset, alen)
             rc = EVP_EncryptUpdate(self.ctx, NULL, &olen, <const unsigned char*> hdata.buf+aoffset, alen)
             if not rc:
             if not rc:
                 raise CryptoError('EVP_EncryptUpdate failed')
                 raise CryptoError('EVP_EncryptUpdate failed')
-            if not EVP_EncryptUpdate(self.ctx, NULL, &olen, odata+offset, 12):
+            if not EVP_EncryptUpdate(self.ctx, NULL, &olen, odata+offset, self.iv_len):
                 raise CryptoError('EVP_EncryptUpdate failed')
                 raise CryptoError('EVP_EncryptUpdate failed')
-            offset += 12
+            offset += self.iv_len
             rc = EVP_EncryptUpdate(self.ctx, odata+offset, &olen, <const unsigned char*> idata.buf, ilen)
             rc = EVP_EncryptUpdate(self.ctx, odata+offset, &olen, <const unsigned char*> idata.buf, ilen)
             if not rc:
             if not rc:
                 raise CryptoError('EVP_EncryptUpdate failed')
                 raise CryptoError('EVP_EncryptUpdate failed')
@@ -401,7 +412,7 @@ cdef class _AEAD_BASE:
             if not rc:
             if not rc:
                 raise CryptoError('EVP_EncryptFinal_ex failed')
                 raise CryptoError('EVP_EncryptFinal_ex failed')
             offset += olen
             offset += olen
-            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_GET_TAG, 16, odata+hlen):
+            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_GET_TAG, self.mac_len, odata+hlen):
                 raise CryptoError('EVP_CIPHER_CTX_ctrl GET TAG failed')
                 raise CryptoError('EVP_CIPHER_CTX_ctrl GET TAG failed')
             self.blocks += num_aes_blocks(ilen)
             self.blocks += num_aes_blocks(ilen)
             return odata[:offset]
             return odata[:offset]
@@ -427,21 +438,24 @@ cdef class _AEAD_BASE:
         try:
         try:
             if not EVP_DecryptInit_ex(self.ctx, self.cipher(), NULL, NULL, NULL):
             if not EVP_DecryptInit_ex(self.ctx, self.cipher(), NULL, NULL, NULL):
                 raise CryptoError('EVP_DecryptInit_ex failed')
                 raise CryptoError('EVP_DecryptInit_ex failed')
-            iv = self.fetch_iv(<unsigned char *> idata.buf+hlen+16)
+            iv = self.fetch_iv(<unsigned char *> idata.buf+hlen+self.mac_len)
             self.set_iv(iv)
             self.set_iv(iv)
-            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL):
+            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_SET_IVLEN, self.iv_len, NULL):
                 raise CryptoError('EVP_CIPHER_CTX_ctrl SET IVLEN failed')
                 raise CryptoError('EVP_CIPHER_CTX_ctrl SET IVLEN failed')
             if not EVP_DecryptInit_ex(self.ctx, NULL, NULL, self.enc_key, iv):
             if not EVP_DecryptInit_ex(self.ctx, NULL, NULL, self.enc_key, iv):
                 raise CryptoError('EVP_DecryptInit_ex failed')
                 raise CryptoError('EVP_DecryptInit_ex failed')
-            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_SET_TAG, 16, <void *> idata.buf+hlen):
+            if not EVP_CIPHER_CTX_ctrl(self.ctx, EVP_CTRL_GCM_SET_TAG, self.mac_len, <void *> idata.buf+hlen):
                 raise CryptoError('EVP_CIPHER_CTX_ctrl SET TAG failed')
                 raise CryptoError('EVP_CIPHER_CTX_ctrl SET TAG failed')
             rc = EVP_DecryptUpdate(self.ctx, NULL, &olen, <const unsigned char*> idata.buf+aoffset, alen)
             rc = EVP_DecryptUpdate(self.ctx, NULL, &olen, <const unsigned char*> idata.buf+aoffset, alen)
             if not rc:
             if not rc:
                 raise CryptoError('EVP_DecryptUpdate failed')
                 raise CryptoError('EVP_DecryptUpdate failed')
-            if not EVP_DecryptUpdate(self.ctx, NULL, &olen, <const unsigned char*> idata.buf+hlen+16, 12):
+            if not EVP_DecryptUpdate(self.ctx, NULL, &olen,
+                                     <const unsigned char*> idata.buf+hlen+self.mac_len, self.iv_len):
                 raise CryptoError('EVP_DecryptUpdate failed')
                 raise CryptoError('EVP_DecryptUpdate failed')
             offset = 0
             offset = 0
-            rc = EVP_DecryptUpdate(self.ctx, odata+offset, &olen, <const unsigned char*> idata.buf+hlen+16+12, ilen-hlen-16-12)
+            rc = EVP_DecryptUpdate(self.ctx, odata+offset, &olen,
+                                   <const unsigned char*> idata.buf+hlen+self.mac_len+self.iv_len,
+                                   ilen-hlen-self.mac_len-self.iv_len)
             if not rc:
             if not rc:
                 raise CryptoError('EVP_DecryptUpdate failed')
                 raise CryptoError('EVP_DecryptUpdate failed')
             offset += olen
             offset += olen
@@ -458,24 +472,24 @@ cdef class _AEAD_BASE:
 
 
     def set_iv(self, iv):
     def set_iv(self, iv):
         self.blocks = 0  # number of cipher blocks encrypted with this IV
         self.blocks = 0  # number of cipher blocks encrypted with this IV
-        for i in range(12):
+        for i in range(self.iv_len):
             self.iv[i] = iv[i]
             self.iv[i] = iv[i]
 
 
     def next_iv(self):
     def next_iv(self):
         assert self.blocks < 2**32
         assert self.blocks < 2**32
         # we need 16 bytes for increment_iv:
         # we need 16 bytes for increment_iv:
-        last_iv = b'\0\0\0\0' + self.iv[:12]
+        last_iv = b'\0' * (16 - self.iv_len) + self.iv[:self.iv_len]
         # gcm mode is special: it appends a internal 32bit counter to the 96bit (12 byte) we provide, thus we only
         # gcm mode is special: it appends a internal 32bit counter to the 96bit (12 byte) we provide, thus we only
         # need to increment the 96bit counter by 1 (and we must not encrypt more than 2^32 AES blocks with same IV):
         # need to increment the 96bit counter by 1 (and we must not encrypt more than 2^32 AES blocks with same IV):
         next_iv = increment_iv(last_iv, 1)
         next_iv = increment_iv(last_iv, 1)
-        return next_iv[-12:]
+        return next_iv[-self.iv_len:]
 
 
     cdef fetch_iv(self, unsigned char * iv_in):
     cdef fetch_iv(self, unsigned char * iv_in):
-        return iv_in[0:12]
+        return iv_in[0:self.iv_len]
 
 
     cdef store_iv(self, unsigned char * iv_out, unsigned char * iv):
     cdef store_iv(self, unsigned char * iv_out, unsigned char * iv):
         cdef int i
         cdef int i
-        for i in range(12):
+        for i in range(self.iv_len):
             iv_out[i] = iv[i]
             iv_out[i] = iv[i]