]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blob - ctypescrypto/mac.py
Added explicit check for CMS functions in libcrypto
[oss/ctypescrypto.git] / ctypescrypto / mac.py
1 # -*- encoding: utf-8 -*-
2 """
3 This module provides interface to OpenSSL MAC functions.
4
5 It has not only HMAC support, but can support other types of MAC.
6
7 """
8
9 from ctypescrypto.digest import Digest,DigestType,DigestError
10 from ctypescrypto.oid import Oid
11 from ctypescrypto import libcrypto
12 from ctypes import c_int,c_char_p, c_void_p, c_size_t,POINTER,create_string_buffer,pointer
13
14 __all__ = ['MAC','DigestError']
15 class MAC(Digest):
16     """
17         This object represents MAC context. It is quite simular
18         to digest algorithm. It is simular to hmac objects provided
19         by standard library
20     """
21     def __init__(self,algorithm,key,digest=None,**kwargs):
22         """
23         Constructor has to obligatory arguments:
24             
25             @param algorithm - which is name of MAC algorithm i.e 'hmac' or 
26                     'gost-mac' or equivalent Oid object
27             @param key - byte buffer with key.
28
29         Optional parameters are:
30             digest - Oid or name of the digest algorithm to use. If none
31                 specified, OpenSSL will try to derive one from the MAC
32                 algorithm (or if algorithm is hmac, we'll substititute md5
33                 for compatibility with standard hmac module
34
35             any other keyword argument is passed to EVP_PKEY_CTX as string
36             option.
37
38         """
39         if isinstance(algorithm,str):
40             self.algorithm=Oid(algorithm)
41         elif isinstance(algorithm,Oid):
42             self.algorithm=algorithm
43         else:
44             raise TypeError("Algorthm must be string or Oid")
45         if self.algorithm==Oid('hmac') and digest is None:
46                 digest='md5'
47         self.name=self.algorithm.shortname().lower()
48         if digest is not None:
49             self.digest_type=DigestType(digest)
50             self.name+='-'+self.digest_type.digest_name
51             d=self.digest_type.digest
52         else:
53             self.digest_type=None
54             d=None
55         self.key=libcrypto.EVP_PKEY_new_mac_key(self.algorithm.nid,None,key,len(key))
56         if self.key is None:
57             raise DigestError("EVP_PKEY_new_mac_key")
58         pctx=c_void_p()
59         self.ctx = self.newctx()
60         if self.ctx == 0:
61             raise DigestError("Unable to create digest context")
62         if libcrypto.EVP_DigestSignInit(self.ctx,pointer(pctx),d,None,self.key) <= 0:
63             raise DigestError("Unable to intialize digest context")
64         self.digest_finalized=False
65         if self.digest_type is None:
66             self.digest_type=DigestType(Oid(libcrypto.EVP_MD_type(libcrypto.EVP_MD_CTX_md(self.ctx))))
67         for (name,val) in kwargs.items():
68             if libcrypto.EVP_PKEY_CTX_ctrl_str(pctx,name,val)<=0:
69                 raise DigestError("Unable to set mac parameter")
70         self.digest_size = self.digest_type.digest_size
71         self.block_size = self.digest_type.block_size
72     def digest(self,data=None):
73         """
74         Method digest is redefined to return keyed MAC value instead of
75         just digest.
76         """
77         if data is not None:
78             self.update(data)
79         b=create_string_buffer(256)
80         size=c_size_t(256)
81         if libcrypto.EVP_DigestSignFinal(self.ctx,b,pointer(size))<=0:
82             raise DigestError('SignFinal')
83         self.digest_finalized=True
84         return b.raw[:size.value]
85
86 libcrypto.EVP_DigestSignFinal.argtypes=(c_void_p,c_char_p,POINTER(c_size_t))
87 libcrypto.EVP_DigestSignFinal.restype=c_int
88 libcrypto.EVP_DigestSignInit.argtypes=(c_void_p,POINTER(c_void_p),c_void_p,c_void_p,c_void_p)
89 libcrypto.EVP_DigestSignInit.restype=c_int
90 libcrypto.EVP_PKEY_CTX_ctrl_str.argtypes=(c_void_p,c_char_p,c_char_p)
91 libcrypto.EVP_PKEY_CTX_ctrl_str.restype=c_int
92 libcrypto.EVP_PKEY_new_mac_key.argtypes=(c_int,c_void_p,c_char_p,c_int)
93 libcrypto.EVP_PKEY_new_mac_key.restype=c_void_p
94 libcrypto.EVP_MD_CTX_md.argtypes=(c_void_p,)
95 libcrypto.EVP_MD_CTX_md.restype=c_void_p