CryptoSys API Library Manual

GCM_NextEncrypt

Carries out the GCM authenticated encryption operation using the key set up by an earlier call to GCM_InitKey.

VBA/VB6 Syntax

Public Declare Function GCM_NextEncrypt Lib "diCryptoSys.dll" (ByVal hContext As Long, 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 lpIV As Byte, ByVal nIvLen As Long, ByRef lpAAD As Byte, ByVal nAadLen As Long) As Long

nRet = GCM_NextEncrypt(hContext, lpOutput(0), nOutLen, abTagOut(0), nTagLen, abData(0), nDataLen, abIV(0), nIvLen, abAAD(0), nAadLen)

C/C++ Syntax

long __stdcall GCM_NextEncrypt(long hContext, unsigned char *lpOutput, long nOutLen, unsigned char *lpTagOut, long nTagLen, const unsigned char *lpData, long nDataLen, const unsigned char *lpIV, long nIvLen, const unsigned char *lpAAD, long nAadLen);

Parameters

hContext
[in] handle to the GCM context set up by an earlier call to GCM_InitKey.
lpOutput
[out] array of sufficient length to receive the ciphertext output.
nOutLen
[in] specifying the required length of the output in bytes.
lpTagOut
[out] array of sufficient length to receive the tag, at least 4 bytes long.
nTagLen
[in] specifying the required length of the tag in bytes.
lpData
[in] array containing the input data.
nDataLen
[in] equal to length of the input data in bytes.
lpIV
[in] containing the initialization vector (IV).
nIvLen
[in] equal to length of the IV in bytes.
lpAAD
[in] array containing the optional Additional Authenticated Data (AAD).
nAadLen
[in] equal to length of the AAD in bytes.

Returns (VBA/C)

If successful, the return value is 0; otherwise it returns a non-zero error code.

.NET Equivalent

Gcm.NextEncrypt Method

Remarks

See the remarks for GCM_Encrypt and the Security considerations for AEAD encryption.

Example

This example uses AES-GCM to create some demo authenticated payloads for IPsec.

Public Sub Test_GCM_IPsec()
' Refs: RFC4106, RFC4303, RFC3602
    Dim abKey() As Byte
    Dim abSPI() As Byte
    Dim abSalt() As Byte
    Dim abIV() As Byte
    Dim abNonce() As Byte
    Dim nKeyLen As Long
    Dim nDataLen As Long
    Dim nNonceLen As Long
    Dim nAadLen As Long
    Dim nTagLen As Long
    Dim nRet As Long
    Dim hContext As Long
    Dim abTail() As Byte
    Dim nSeq As Long
    Dim abPlain() As Byte
    Dim abAAD() As Byte
    Dim abTag() As Byte
    Dim abCipher() As Byte
    Dim abPayload() As Byte
    Dim abCheck() As Byte
    Dim strCheck As String
    
    Dim asBlocks As Variant
    Dim nBlocks As Long
    ' Data we will send = text in blocks of 44 bytes
    ' (We use an array of strings here for our demo
    ' -- in practice, deal with input and its length as it comes)
    asBlocks = Array( _
        "From fairest creatures we desire increase,  ", _
        "That thereby beauty's rose might never die, ", _
        "But as the riper should by time decease,    ", _
        "His tender heir might bear his memory:      " _
    )
    nBlocks = UBound(asBlocks) + 1

    ' Test values -- in practice, these should be generated uniquely
    abKey = cnvBytesFromHexStr("90d382b410eeba7ad938c46cec1a82bf")
    abSalt = cnvBytesFromHexStr("e96e8c08")
    abSPI = cnvBytesFromHexStr("00004321")
    
    ' Constant lengths
    nKeyLen = 16
    nNonceLen = 12
    nAadLen = 8
    nTagLen = 8
    
    ReDim abTag(nTagLen - 1)
    
    ' IP padding + pad length + next header
    ' -- in this case always the same
    abTail = cnvBytesFromHexStr("01020201")
    
    ' Initialize AES-GCM key
    hContext = GCM_InitKey(abKey(0), nKeyLen, 0)
    If hContext = 0 Then
        Debug.Print "ERROR: GCM_InitKey failed"
        Exit Sub
    End If
    Debug.Print "KEY=" & cnvHexStrFromBytes(abKey)
    
    ' Process each block of data
    For nSeq = 1 To nBlocks
        Debug.Print "Seq #=" & nSeq
        ' 8-byte IV to ESP = 4-byte SPI || 4-byte SeqNum
        abIV = BytesConcat(abSPI, BytesFromWord32(nSeq))
        Debug.Print "IV =" & cnvHexStrFromBytes(abIV)
        ' 12-byte nonce to AES-GCM = 4-byte salt || 8-byte IV
        abNonce = BytesConcat(abSalt, abIV)
        Debug.Print "NON=" & cnvHexStrFromBytes(abNonce)
        ' Create AAD = 4-byte SPI || 4-byte SeqNum
        abAAD = BytesConcat(abSPI, BytesFromWord32(nSeq))
        Debug.Print "AAD=" & cnvHexStrFromBytes(abAAD)
        ' Create pre-encryption data = text block converted to byte array || tail
        abPlain = StrConv(asBlocks(nSeq - 1), vbFromUnicode)
        ' in this case, the padding is always the same...
        abPlain = BytesConcat(abPlain, abTail)
        Debug.Print "Pre-encryption Data (" & UBound(abPlain) + 1 & " bytes):" & vbCrLf & cnvHexStrFromBytes(abPlain)
        nDataLen = UBound(abPlain) + 1
        ' Encrypt it
        ReDim abCipher(nDataLen - 1)
        nRet = GCM_NextEncrypt(hContext, abCipher(0), nDataLen, abTag(0), nTagLen, _
            abPlain(0), nDataLen, abNonce(0), nNonceLen, abAAD(0), nAadLen)
        Debug.Print "GCM_NextEncrypt returns " & nRet & " (expected 0)"
        ' Display the parts...
        Debug.Print "IP DATAGRAM PAYLOAD:"
        Debug.Print "SPI/Seq #: " & cnvHexStrFromBytes(abSPI) & " " & cnvHexStrFromBytes(BytesFromWord32(nSeq))
        Debug.Print "IV: " & cnvHexStrFromBytes(abIV)
        Debug.Print "Encrypted Data (" & UBound(abCipher) + 1 & " bytes):" & vbCrLf & cnvHexStrFromBytes(abCipher)
        Debug.Print "ICV: " & cnvHexStrFromBytes(abTag)
        ' Compose IP payload
        abPayload = BytesConcat(abSPI, BytesFromWord32(nSeq))
        abPayload = BytesConcat(abPayload, abIV)
        abPayload = BytesConcat(abPayload, abCipher)
        abPayload = BytesConcat(abPayload, abTag)
        Debug.Print "Payload (" & UBound(abPayload) + 1 & " bytes):" & vbCrLf & cnvHexStrFromBytes(abPayload)
        
        ' To show this works, decrypt it as we go
        ' -- in practice, you'd need to recreate the nonce and the AAD
        ReDim abCheck(nDataLen - 1)
        nRet = GCM_NextDecrypt(hContext, abCheck(0), nDataLen, abCipher(0), nDataLen, _
            abNonce(0), nNonceLen, abAAD(0), nAadLen, abTag(0), nTagLen)
        Debug.Print "GCM_NextDecrypt returns " & nRet & " (expected 0)"
        strCheck = StrConv(abCheck, vbUnicode)
        ' -- in practice, you'd need to strip the padding, but we fudge here...
        Debug.Print "PT: [" & Left(strCheck, 44) & "]"
        
    Next
    
    Call GCM_FinishKey(hContext)

End Sub

' Some helper functions to deal with Byte arrays...
Private Function BytesConcat(ab1() As Byte, ab2() As Byte) As Variant
' Return ab1 || ab2
    Dim ab3() As Byte
    Dim i As Long
    ab3 = ab1
    ReDim Preserve ab3(UBound(ab1) + UBound(ab2) + 1)
    For i = 0 To UBound(ab2)
        ab3(i + UBound(ab1) + 1) = ab2(i)
    Next
    BytesConcat = ab3
End Function

Private Function BytesFromWord32(ByVal w As Long) As Variant
' Split 32-bit word w into 4-byte long Byte array (network order)
    Dim abArray() As Byte
    ReDim abArray(3)
    abArray(0) = CByte(((w And &HFF000000) \ &H1000000) And &HFF)
    abArray(1) = CByte(((w And &HFF0000) \ &H10000) And &HFF)
    abArray(2) = CByte(((w And &HFF00) \ &H100) And &HFF)
    abArray(3) = CByte((w And &HFF) And &HFF)
    BytesFromWord32 = abArray
End Function

See Also

GCM_InitKey GCM_NextDecrypt

[Contents] [Index]

[PREV: GCM_NextDecrypt...]   [Contents]   [Index]   
   [NEXT: HASH_AddBytes...]

Copyright © 2001-24 D.I. Management Services Pty Ltd. All rights reserved. Generated 2024-01-07T07:42:00Z.