
SHA1 is no longer secure and thus needs to be replaced by a secure algorithm, in this case SHA256. See: https://en.wikipedia.org/wiki/SHA-1#Attacks Fixes: https://github.com/cloudbase/cloudbase-init/issues/123 Change-Id: Ib565b99116fe966421f57b6c1f3bf6d6b9589288 Signed-off-by: Adrian Vladu <avladu@cloudbasesolutions.com>
335 lines
12 KiB
Python
335 lines
12 KiB
Python
# Copyright 2013 Cloudbase Solutions Srl
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import ctypes
|
|
|
|
from ctypes import windll
|
|
from ctypes import wintypes
|
|
|
|
|
|
class CryptoAPIException(Exception):
|
|
|
|
def __init__(self):
|
|
message = self._get_windows_error()
|
|
super(CryptoAPIException, self).__init__(message)
|
|
|
|
def _get_windows_error(self):
|
|
err_code = GetLastError()
|
|
return "CryptoAPI error: 0x%0x" % err_code
|
|
|
|
|
|
class SYSTEMTIME(ctypes.Structure):
|
|
_fields_ = [
|
|
('wYear', wintypes.WORD),
|
|
('wMonth', wintypes.WORD),
|
|
('wDayOfWeek', wintypes.WORD),
|
|
('wDay', wintypes.WORD),
|
|
('wHour', wintypes.WORD),
|
|
('wMinute', wintypes.WORD),
|
|
('wSecond', wintypes.WORD),
|
|
('wMilliseconds', wintypes.WORD),
|
|
]
|
|
|
|
|
|
class FILETIME(ctypes.Structure):
|
|
_fields_ = [
|
|
('dwLowDateTime', wintypes.DWORD),
|
|
('dwHighDateTime', wintypes.DWORD),
|
|
]
|
|
|
|
|
|
class CERT_CONTEXT(ctypes.Structure):
|
|
_fields_ = [
|
|
('dwCertEncodingType', wintypes.DWORD),
|
|
('pbCertEncoded', ctypes.POINTER(wintypes.BYTE)),
|
|
('cbCertEncoded', wintypes.DWORD),
|
|
('pCertInfo', ctypes.c_void_p),
|
|
('hCertStore', wintypes.HANDLE),
|
|
]
|
|
|
|
|
|
class CRYPTOAPI_BLOB(ctypes.Structure):
|
|
_fields_ = [
|
|
('cbData', wintypes.DWORD),
|
|
('pbData', ctypes.POINTER(wintypes.BYTE)),
|
|
]
|
|
|
|
|
|
class CRYPT_ALGORITHM_IDENTIFIER(ctypes.Structure):
|
|
_fields_ = [
|
|
('pszObjId', wintypes.LPSTR),
|
|
('Parameters', CRYPTOAPI_BLOB),
|
|
]
|
|
|
|
|
|
class CRYPT_KEY_PROV_PARAM(ctypes.Structure):
|
|
_fields_ = [
|
|
('dwParam', wintypes.DWORD),
|
|
('pbData', ctypes.POINTER(wintypes.BYTE)),
|
|
('cbData', wintypes.DWORD),
|
|
('dwFlags', wintypes.DWORD),
|
|
]
|
|
|
|
|
|
class CRYPT_KEY_PROV_INFO(ctypes.Structure):
|
|
_fields_ = [
|
|
('pwszContainerName', wintypes.LPWSTR),
|
|
('pwszProvName', wintypes.LPWSTR),
|
|
('dwProvType', wintypes.DWORD),
|
|
('dwFlags', wintypes.DWORD),
|
|
('cProvParam', wintypes.DWORD),
|
|
('cProvParam', ctypes.POINTER(CRYPT_KEY_PROV_PARAM)),
|
|
('dwKeySpec', wintypes.DWORD),
|
|
]
|
|
|
|
|
|
class CRYPT_DECRYPT_MESSAGE_PARA(ctypes.Structure):
|
|
_fields_ = [
|
|
('cbSize', wintypes.DWORD),
|
|
('dwMsgAndCertEncodingType', wintypes.DWORD),
|
|
('cCertStore', wintypes.DWORD),
|
|
('rghCertStore', ctypes.POINTER(wintypes.HANDLE)),
|
|
('dwFlags', wintypes.DWORD),
|
|
]
|
|
|
|
|
|
class CERT_KEY_CONTEXT(ctypes.Structure):
|
|
_fields_ = [
|
|
('cbSize', wintypes.DWORD),
|
|
('hNCryptKey', wintypes.HANDLE),
|
|
('dwKeySpec', wintypes.DWORD),
|
|
]
|
|
|
|
|
|
AT_KEYEXCHANGE = 1
|
|
AT_SIGNATURE = 2
|
|
CERT_NAME_UPN_TYPE = 8
|
|
CERT_SHA1_HASH_PROP_ID = 3
|
|
CERT_STORE_ADD_REPLACE_EXISTING = 3
|
|
CERT_STORE_PROV_MEMORY = wintypes.LPSTR(2)
|
|
CERT_STORE_PROV_SYSTEM = wintypes.LPSTR(10)
|
|
CERT_SYSTEM_STORE_CURRENT_USER = 0x10000
|
|
CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x20000
|
|
CERT_X500_NAME_STR = 3
|
|
CERT_STORE_ADD_NEW = 1
|
|
CERT_STORE_OPEN_EXISTING_FLAG = 0x4000
|
|
CERT_STORE_CREATE_NEW_FLAG = 0x2000
|
|
CRYPT_SILENT = 64
|
|
CRYPT_MACHINE_KEYSET = 32
|
|
CRYPT_NEWKEYSET = 8
|
|
CRYPT_STRING_BASE64 = 1
|
|
PKCS_7_ASN_ENCODING = 0x10000
|
|
PROV_RSA_FULL = 1
|
|
X509_ASN_ENCODING = 1
|
|
CERT_FIND_ANY = 0
|
|
CERT_FIND_SHA1_HASH = 0x10000
|
|
CERT_KEY_PROV_INFO_PROP_ID = 2
|
|
CERT_KEY_CONTEXT_PROP_ID = 5
|
|
|
|
# https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-crypt_algorithm_identifier
|
|
szOID_PKIX_KP_SERVER_AUTH = b"1.3.6.1.5.5.7.3.1"
|
|
szOID_RSA_SHA1RSA = b"1.2.840.113549.1.1.5"
|
|
szOID_RSA_SHA256RSA = b"1.2.840.113549.1.1.11"
|
|
|
|
advapi32 = windll.advapi32
|
|
crypt32 = windll.crypt32
|
|
kernel32 = windll.kernel32
|
|
|
|
advapi32.CryptAcquireContextW.restype = wintypes.BOOL
|
|
advapi32.CryptAcquireContextW.argtypes = [wintypes.HANDLE, wintypes.LPCWSTR,
|
|
wintypes.LPCWSTR, wintypes.DWORD,
|
|
wintypes.DWORD]
|
|
CryptAcquireContext = advapi32.CryptAcquireContextW
|
|
|
|
advapi32.CryptReleaseContext.restype = wintypes.BOOL
|
|
advapi32.CryptReleaseContext.argtypes = [wintypes.HANDLE, wintypes.DWORD]
|
|
CryptReleaseContext = advapi32.CryptReleaseContext
|
|
|
|
advapi32.CryptGenKey.restype = wintypes.BOOL
|
|
advapi32.CryptGenKey.argtypes = [wintypes.HANDLE,
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
ctypes.POINTER(wintypes.HANDLE)]
|
|
CryptGenKey = advapi32.CryptGenKey
|
|
|
|
advapi32.CryptDestroyKey.restype = wintypes.BOOL
|
|
advapi32.CryptDestroyKey.argtypes = [wintypes.HANDLE]
|
|
CryptDestroyKey = advapi32.CryptDestroyKey
|
|
|
|
crypt32.CertStrToNameW.restype = wintypes.BOOL
|
|
crypt32.CertStrToNameW.argtypes = [wintypes.DWORD, wintypes.LPCWSTR,
|
|
wintypes.DWORD, ctypes.c_void_p,
|
|
ctypes.POINTER(wintypes.BYTE),
|
|
ctypes.POINTER(wintypes.DWORD),
|
|
ctypes.POINTER(wintypes.LPCWSTR)]
|
|
CertStrToName = crypt32.CertStrToNameW
|
|
|
|
# TODO(alexpilotti): the following time related functions are not CryptoAPI
|
|
# specific, putting them in a separate module would be more correct
|
|
kernel32.GetSystemTime.restype = None
|
|
kernel32.GetSystemTime.argtypes = [ctypes.POINTER(SYSTEMTIME)]
|
|
GetSystemTime = kernel32.GetSystemTime
|
|
|
|
kernel32.SystemTimeToFileTime.restype = wintypes.BOOL
|
|
kernel32.SystemTimeToFileTime.argtypes = [ctypes.POINTER(SYSTEMTIME),
|
|
ctypes.POINTER(FILETIME)]
|
|
SystemTimeToFileTime = kernel32.SystemTimeToFileTime
|
|
|
|
kernel32.FileTimeToSystemTime.restype = wintypes.BOOL
|
|
kernel32.FileTimeToSystemTime.argtypes = [ctypes.POINTER(FILETIME),
|
|
ctypes.POINTER(SYSTEMTIME)]
|
|
FileTimeToSystemTime = kernel32.FileTimeToSystemTime
|
|
|
|
# TODO(alexpilotti): this is not a CryptoAPI function, putting it in a separate
|
|
# module would be more correct
|
|
kernel32.GetLastError.restype = wintypes.DWORD
|
|
kernel32.GetLastError.argtypes = []
|
|
GetLastError = kernel32.GetLastError
|
|
|
|
crypt32.CertCreateSelfSignCertificate.restype = ctypes.POINTER(CERT_CONTEXT)
|
|
crypt32.CertCreateSelfSignCertificate.argtypes = [
|
|
wintypes.HANDLE,
|
|
ctypes.POINTER(CRYPTOAPI_BLOB),
|
|
wintypes.DWORD,
|
|
ctypes.POINTER(CRYPT_KEY_PROV_INFO),
|
|
ctypes.POINTER(CRYPT_ALGORITHM_IDENTIFIER),
|
|
ctypes.POINTER(SYSTEMTIME),
|
|
ctypes.POINTER(SYSTEMTIME),
|
|
# PCERT_EXTENSIONS
|
|
ctypes.c_void_p]
|
|
CertCreateSelfSignCertificate = crypt32.CertCreateSelfSignCertificate
|
|
|
|
crypt32.CertAddEnhancedKeyUsageIdentifier.restype = wintypes.BOOL
|
|
crypt32.CertAddEnhancedKeyUsageIdentifier.argtypes = [
|
|
ctypes.POINTER(CERT_CONTEXT),
|
|
wintypes.LPCSTR]
|
|
CertAddEnhancedKeyUsageIdentifier = crypt32.CertAddEnhancedKeyUsageIdentifier
|
|
|
|
crypt32.CertOpenStore.restype = wintypes.HANDLE
|
|
crypt32.CertOpenStore.argtypes = [wintypes.LPCSTR, wintypes.DWORD,
|
|
wintypes.HANDLE, wintypes.DWORD,
|
|
ctypes.c_void_p]
|
|
CertOpenStore = crypt32.CertOpenStore
|
|
|
|
crypt32.CertAddCertificateContextToStore.restype = wintypes.BOOL
|
|
crypt32.CertAddCertificateContextToStore.argtypes = [
|
|
wintypes.HANDLE,
|
|
ctypes.POINTER(CERT_CONTEXT),
|
|
wintypes.DWORD,
|
|
ctypes.POINTER(CERT_CONTEXT)]
|
|
CertAddCertificateContextToStore = crypt32.CertAddCertificateContextToStore
|
|
|
|
crypt32.CryptStringToBinaryW.restype = wintypes.BOOL
|
|
crypt32.CryptStringToBinaryW.argtypes = [wintypes.LPCWSTR,
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
ctypes.POINTER(wintypes.BYTE),
|
|
ctypes.POINTER(wintypes.DWORD),
|
|
ctypes.POINTER(wintypes.DWORD),
|
|
ctypes.POINTER(wintypes.DWORD)]
|
|
CryptStringToBinaryW = crypt32.CryptStringToBinaryW
|
|
|
|
crypt32.CertAddEncodedCertificateToStore.restype = wintypes.BOOL
|
|
crypt32.CertAddEncodedCertificateToStore.argtypes = [
|
|
wintypes.HANDLE,
|
|
wintypes.DWORD,
|
|
ctypes.POINTER(wintypes.BYTE),
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
ctypes.POINTER(ctypes.POINTER(CERT_CONTEXT))]
|
|
CertAddEncodedCertificateToStore = crypt32.CertAddEncodedCertificateToStore
|
|
|
|
crypt32.CertGetNameStringW.restype = wintypes.DWORD
|
|
crypt32.CertGetNameStringW.argtypes = [ctypes.POINTER(CERT_CONTEXT),
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
ctypes.c_void_p,
|
|
wintypes.LPWSTR,
|
|
wintypes.DWORD]
|
|
CertGetNameString = crypt32.CertGetNameStringW
|
|
|
|
crypt32.CertFreeCertificateContext.restype = wintypes.BOOL
|
|
crypt32.CertFreeCertificateContext.argtypes = [ctypes.POINTER(CERT_CONTEXT)]
|
|
CertFreeCertificateContext = crypt32.CertFreeCertificateContext
|
|
|
|
crypt32.CertCloseStore.restype = wintypes.BOOL
|
|
crypt32.CertCloseStore.argtypes = [wintypes.HANDLE, wintypes.DWORD]
|
|
CertCloseStore = crypt32.CertCloseStore
|
|
|
|
crypt32.CertGetCertificateContextProperty.restype = wintypes.BOOL
|
|
crypt32.CertGetCertificateContextProperty.argtypes = [
|
|
ctypes.POINTER(CERT_CONTEXT),
|
|
wintypes.DWORD,
|
|
ctypes.c_void_p,
|
|
ctypes.POINTER(wintypes.DWORD)]
|
|
CertGetCertificateContextProperty = crypt32.CertGetCertificateContextProperty
|
|
|
|
crypt32.CryptBinaryToStringW.restype = wintypes.BOOL
|
|
crypt32.CryptBinaryToStringW.argtypes = [
|
|
ctypes.c_void_p,
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
wintypes.LPWSTR,
|
|
ctypes.POINTER(wintypes.DWORD)]
|
|
CryptBinaryToString = crypt32.CryptBinaryToStringW
|
|
|
|
crypt32.CryptDecryptMessage.restype = wintypes.BOOL
|
|
crypt32.CryptDecryptMessage.argtypes = [
|
|
ctypes.POINTER(CRYPT_DECRYPT_MESSAGE_PARA),
|
|
ctypes.c_void_p,
|
|
wintypes.DWORD,
|
|
ctypes.c_void_p,
|
|
ctypes.POINTER(wintypes.DWORD),
|
|
ctypes.c_void_p]
|
|
CryptDecryptMessage = crypt32.CryptDecryptMessage
|
|
|
|
crypt32.CertAddCertificateLinkToStore.restype = wintypes.BOOL
|
|
crypt32.CertAddCertificateLinkToStore.argtypes = [
|
|
wintypes.HANDLE,
|
|
ctypes.POINTER(CERT_CONTEXT),
|
|
wintypes.DWORD,
|
|
ctypes.c_void_p
|
|
]
|
|
CertAddCertificateLinkToStore = crypt32.CertAddCertificateLinkToStore
|
|
|
|
crypt32.CertFindCertificateInStore.restype = ctypes.POINTER(CERT_CONTEXT)
|
|
crypt32.CertFindCertificateInStore.argtypes = [
|
|
wintypes.HANDLE,
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
ctypes.c_void_p,
|
|
ctypes.c_void_p]
|
|
CertFindCertificateInStore = crypt32.CertFindCertificateInStore
|
|
|
|
crypt32.CertSetCertificateContextProperty.restype = wintypes.BOOL
|
|
crypt32.CertSetCertificateContextProperty.argtypes = [
|
|
ctypes.POINTER(CERT_CONTEXT),
|
|
wintypes.DWORD,
|
|
wintypes.DWORD,
|
|
ctypes.c_void_p]
|
|
CertSetCertificateContextProperty = crypt32.CertSetCertificateContextProperty
|
|
|
|
crypt32.PFXImportCertStore.restype = wintypes.HANDLE
|
|
crypt32.PFXImportCertStore.argtypes = [
|
|
ctypes.POINTER(CRYPTOAPI_BLOB),
|
|
wintypes.LPCWSTR,
|
|
wintypes.DWORD]
|
|
PFXImportCertStore = crypt32.PFXImportCertStore
|
|
|
|
crypt32.CertDeleteCertificateFromStore.restype = wintypes.BOOL
|
|
crypt32.CertDeleteCertificateFromStore.argtypes = [
|
|
ctypes.POINTER(CERT_CONTEXT)]
|
|
CertDeleteCertificateFromStore = crypt32.CertDeleteCertificateFromStore
|