Provides authenticated encryption using the Galois/Counter Mode (GCM) of operation with the AES algorithm (AES-GCM). It can also provide a stand-alone message authentication code (GMAC). All the input and output parameters are in byte arrays.
Public Declare Function GCM_Encrypt Lib "diCryptoSys.dll" (ByRef lpOutput As Byte, ByVal nOutLen As Long, ByRef lpTagOut As Byte, ByVal nTagLen As Long, ByRef lpData As Byte, ByVal nDataLen As Long, ByRef lpKey As Byte, ByVal nKeyLen As Long, ByRef lpIV As Byte, ByVal nIvLen As Long, ByRef lpAAD As Byte, ByVal nAadLen As Long, ByVal nOptions As Long) As Long
nRet = GCM_Encrypt(lpOutput(0), nOutLen, abTagOut(0), nTagLen, abData(0), nDataLen,
abKey(0), nKeyLen, abIV(0), nIvLen, abAAD(0), nAadLen, nOptions)
long __stdcall GCM_Encrypt(unsigned char *lpOutput, long nOutLen, unsigned char *lpTagOut, long nTagLen, const unsigned char *lpData, long nDataLen, const unsigned char *lpKey, long nKeyLen, const unsigned char *lpIV, long nIvLen, const unsigned char *lpAAD, long nAadLen, long nOptions);
If successful, the return value is 0; otherwise it returns a non-zero error code.
This is a one-off, stateless function. If you need to use the same key repeatedly, use
GCM_InitKey
-
GCM_NextEncrypt
-
GCM_FinishKey
instead.
The output lpOutput must be at least as long as the input, or zero length for GMAC.
There are four inputs for authenticated encryption: the secret key, an initialization vector (IV),
the plaintext itself, and optional additional authentication data (AAD). The IV and AAD are passed in the clear.
There are two outputs: the ciphertext, which is exactly the same length as the plaintext, and
an authentication tag (the "tag").
The tag length can be any length from 4 to 16 bytes (API_MAX_GMAC_BYTES
); that is, 32 to 128 bits.
You can truncate the tag value afterwards should you wish, at the cost of reduced security.
The IV can, in principle, be any length, but 12 bytes (96 bits) is recommended as the algorithm is optimised for that length.
The AES algorithm is decided by the length of key you pass: 16 bytes for AES-128, 24 for AES-192, 32 for AES-256; otherwise an error.
See Security considerations for AEAD encryption.
To produce a message authentication code (GMAC), pass an empty or null string for the plaintext input lpData and a zero length nOutLen for the output ciphertext. The "message" is passed in the AAD parameter and the GMAC value is output in the tag. A unique IV is still required.
This is Test Case 4 from Appendix B of [MCGR05].
Dim abKey() As Byte Dim abPlain() As Byte Dim abAAD() As Byte Dim abIV() As Byte Dim abTag() As Byte Dim abCipher() As Byte Dim abCheck() As Byte Dim nKeyLen As Long Dim nDataLen As Long Dim nIVLen As Long Dim nAadLen As Long Dim nTagLen As Long Dim nRet As Long ' Test Case 4: ' Convert test vectors from hex to byte array format abKey = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308") abPlain = cnvBytesFromHexStr("d9313225f88406e5a55909c5aff5269a" & _ "86a7a9531534f7da2e4c303d8a318a72" & _ "1c3c0c95956809532fcf0e2449a6b525" & _ "b16aedf5aa0de657ba637b39") abAAD = cnvBytesFromHexStr("feedfacedeadbeeffeedfacedeadbeef" & _ "abaddad2") abIV = cnvBytesFromHexStr("cafebabefacedbaddecaf888") ' and compute lengths nKeyLen = UBound(abKey) + 1 nDataLen = UBound(abPlain) + 1 nIVLen = UBound(abIV) + 1 nAadLen = UBound(abAAD) + 1 ' Dimension output arrays nTagLen = API_MAX_GMAC_BYTES ReDim abTag(nTagLen - 1) ReDim abCipher(nDataLen - 1) ' Do the business nRet = GCM_Encrypt(abCipher(0), nDataLen, abTag(0), nTagLen, _ abPlain(0), nDataLen, _ abKey(0), nKeyLen, abIV(0), nIVLen, abAAD(0), nAadLen, 0) Debug.Print "GCM_Encrypt returns " & nRet & " (expecting 0)" Debug.Print "CT =" & cnvHexStrFromBytes(abCipher) Debug.Print "TAG=" & cnvHexStrFromBytes(abTag) ' Check we can decrypt ReDim abCheck(nDataLen - 1) nRet = GCM_Decrypt(abCheck(0), nDataLen, abCipher(0), nDataLen, _ abKey(0), nKeyLen, abIV(0), nIVLen, abAAD(0), nAadLen, _ abTag(0), nTagLen, 0) Debug.Print "GCM_Decrypt returns " & nRet & " (expecting 0)" Debug.Print "PT'=" & cnvHexStrFromBytes(abCheck) Debug.Print "PT =" & cnvHexStrFromBytes(abPlain)
This should result in output as follows:
GCM_Encrypt returns 0 (expecting 0) CT =42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E091 TAG=5BC94FBC3221A5DB94FAE95AE7121A47 GCM_Decrypt returns 0 (expecting 0) PT'=D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39 PT =D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39
This is a GMAC test vector:
Dim abKey() As Byte Dim abAAD() As Byte Dim abIV() As Byte Dim abTag() As Byte Dim nKeyLen As Long Dim nAadLen As Long Dim nIvLen As Long Dim nTagLen As Long Dim nRet As Long ' Source: http://www.mail-archive.com/stds-p1619@listserv.ieee.org/msg00321.html ' KEY feffe9928665731c6d6a8f9467308308 ' IV cafebabefacedbaddecaf888 ' AAD feedfacedeadbeeffeedfacedeadbeef ' TAG 54df474f4e71a9ef8a09bf30da7b1a92 abKey = cnvBytesFromHexStr("feffe9928665731c6d6a8f9467308308") abIV = cnvBytesFromHexStr("cafebabefacedbaddecaf888") abAAD = cnvBytesFromHexStr("feedfacedeadbeeffeedfacedeadbeef") nKeyLen = UBound(abKey) + 1 nIvLen = UBound(abIV) + 1 nAadLen = UBound(abAAD) + 1 Debug.Print "KEY " & cnvHexStrFromBytes(abKey) Debug.Print "IV " & cnvHexStrFromBytes(abIV) Debug.Print "AAD " & cnvHexStrFromBytes(abAAD) ' Dimension output array nTagLen = API_MAX_GMAC_BYTES ReDim abTag(nTagLen - 1) ' GMAC := Encrypt with no CT output or PT input. GMAC value is in tag. nRet = GCM_Encrypt(0, 0, abTag(0), nTagLen, 0, 0, _ abKey(0), nKeyLen, abIV(0), nIvLen, abAAD(0), nAadLen, 0) Debug.Print "TAG " & cnvHexStrFromBytes(abTag) Debug.Print "OK " & "54df474f4e71a9ef8a09bf30da7b1a92"
This should result in output as follows:
KEY FEFFE9928665731C6D6A8F9467308308 IV CAFEBABEFACEDBADDECAF888 AAD FEEDFACEDEADBEEFFEEDFACEDEADBEEF TAG 54DF474F4E71A9EF8A09BF30DA7B1A92 OK 54df474f4e71a9ef8a09bf30da7b1a92
GCM_Decrypt
GCM_InitKey
GCM_NextEncrypt