I have a task to develope a CNG. I got a working source code of CNG which supports some algorithms like GOST and etc. I need to make it to generate private key (pkcs8 format) and support x509 certificates in other structures. For example:
this is private key which is generated by this CNG in PKCS8:
3042020100301906092A865C030F01010201300C060A2A865C030F010102010104220220583E4721B1854891532AC05E7033B77D2D357A418A99D473CF05125EA6BDE2C8
ASN1:
SEQUENCE(3 elem)
INTEGER 0
SEQUENCE(2 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1
SEQUENCE(1 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1.1
OCTET STRING(1 elem)
INTEGER(255 bit) 3991356612570766941491045091107680786406690561132958956606466907746255…
I need to make it to generate private key (pkcs8) in this structure:
30819A020100301706092A865C030F01010201060A2A865C030F0101020101047C307A020101042024342757366A76776A2E13580929AD7E3D26B2C11656F30CD7CAF32A354B78D5A00C060A2A865C030F0101020101A145034300044058713A68F3EF7AD72BE6DFCCEBC6576A37B97E2A753C5A34FAA0C3BC818AE461E6F0E2C397BCBFF1314B19A25AF30DCD2653F90B1D73908EB5568D0BAFA87DD1
ASN1:
SEQUENCE(3 elem)
INTEGER 0
SEQUENCE(2 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1.1
OCTET STRING(1 elem)
SEQUENCE(4 elem)
INTEGER 1
OCTET STRING(32 byte) 24342757366A76776A2E13580929AD7E3D26B2C11656F30CD7CAF32A354B78D5
[0](1 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1.1
[1](1 elem)
BIT STRING(1 elem)
OCTET STRING(64 byte) 58713A68F3EF7AD72BE6DFCCEBC6576A37B97E2A753C5A34FAA0C3BC818AE461E6F0E2…
does anyone can help me with it, where I should look for to change any ideas or solutions.
The following function allocates memory and generates the ASN buffers of the private key, Algorithm parameters and the name of the algorithm for the given CNG Blob. These buffers are required to fill the structure Crypt_private_key_info. I think I need to change this piece of code:
SxKS_AllocAndEncodePrivateKey(
__in PBYTE pbKeyBlobCNG,
__in DWORD cbKeyBlobCNG,
__out PBYTE *ppbKeyBufASN,
__out DWORD *pcbKeyBufASN,
__out PBYTE *ppbAlgParamASN,
__out DWORD *pcbAlgParamASN,
__out LPSTR *pszAlgOID)
{
PBYTE pbKeyBufASN = NULL;
DWORD cbKeyBufASN = 0;
PBYTE pbAlgParamASN = NULL;
DWORD cbAlgParamASN = 0;
LPSTR szAlgOID = NULL;
PSTYX_SYMMKEY_BLOB pSymmBlob = NULL;
PSTYX_ASYMMKEY_BLOB pAsymmBlob = NULL;
PSTYX_KEYBLOB_HEADER pHdrBlob = NULL;
SECURITY_STATUS Status = ERROR_SUCCESS;
ULONG dwPubParamId = 0;
ULONG dwMDParamId = 0;
ULONG dwEncParamId = 0;
ULONG cbParam1 = 0;
ULONG cbParam2 = 0;
PBYTE pPrivKeyData;
DWORD fLeadingZero = 0;
// Проверяем входные данные
if ((NULL == pbKeyBlobCNG) ||
(0 == cbKeyBlobCNG) ||
(NULL == ppbKeyBufASN) ||
(NULL == pcbKeyBufASN) ||
(NULL == ppbAlgParamASN) ||
(NULL == pcbAlgParamASN) ||
(NULL == pszAlgOID))
{
Status = NTE_BAD_DATA;
goto Cleanup;
}
pHdrBlob = (PSTYX_KEYBLOB_HEADER)pbKeyBlobCNG;
// Проверяем корректность блоба
if (0 == pHdrBlob->cbKey)
{
Status = NTE_BAD_DATA;
goto Cleanup;
}
pAsymmBlob = (PSTYX_ASYMMKEY_BLOB)pbKeyBlobCNG;
// Проверяем корректность блоба
// Длина ключа
if ((sizeof(STYX_ASYMMKEY_BLOB) + 3 * pAsymmBlob->cbKey) < cbKeyBlobCNG)
{
Status = NTE_BAD_DATA;
goto Cleanup;
}
dwPubParamId = pAsymmBlob->dwPubParamId;
// При необходимости задаем параметры алгоритма по умолчанию.
if (0 == dwPubParamId)
dwPubParamId = 2;
dwMDParamId = pAsymmBlob->dwMDParamId;
// При необходимости задаем блок подстановок хэш по умолчанию.
if (0 == dwMDParamId)
dwMDParamId = 10;
dwEncParamId = pAsymmBlob->dwEncParamId;
// При необходимости задаем блок подстановок по умолчанию.
if (0 == dwEncParamId)
dwEncParamId = 2;
// Устанавливаем указатель значения закрытого ключа
pPrivKeyData = pbKeyBlobCNG + sizeof(STYX_ASYMMKEY_BLOB) + 2 * pAsymmBlob->cbKey;
// Считаем размер для ASN буфера закрытого ключа
// TRIPLET INTEGER (1) + LENGTH (1) + KEYDATA (32) = 34
cbKeyBufASN = 2 + pAsymmBlob->cbKey;
// Устанавливаем флаг fLeadingZero для триплета INTEGER
if (0x80 == (0x80 & pPrivKeyData[0]))
{
fLeadingZero = 1;
cbKeyBufASN++;
}
// Выделяем память для ASN буфера закрытого ключа
pbKeyBufASN = (PBYTE)STYXMALLOC(cbKeyBufASN);
if (NULL == pbKeyBufASN)
{
Status = NTE_NO_MEMORY;
goto Cleanup;
}
// Заполняем ASN буфер закрытого ключа
pbKeyBufASN[0] = 0x02; // ASN.1 TRIPLET TYPE INTEGER
pbKeyBufASN[1] = (BYTE) pAsymmBlob->cbKey; // ASN.1 TRIPLET LENGTH 32 octets
if (1 == fLeadingZero)
{
pbKeyBufASN[1]++;
pbKeyBufASN[2] = 0;
memcpy(pbKeyBufASN + 3, pPrivKeyData, pAsymmBlob->cbKey);
}
else
{
memcpy(pbKeyBufASN + 2, pPrivKeyData, pAsymmBlob->cbKey);
}
// Считаем размер для ASN буфера параметров алгоритма
// TRIPLET SEQ (1) + SEQLEN(1) +
// OBJ(1) + OBJLEN(1) + PubParamOIDdata +
// OBJ(1) + OBJLEN(1) + MDParamOIDdata
SxH_GetOIDoctets_fromGS01PubParamID(dwPubParamId, NULL, &cbParam1);
SxH_GetOIDoctets_fromSBoxID(dwMDParamId, NULL, &cbParam2);
cbAlgParamASN = 6 + (BYTE)(cbParam1 + cbParam2);
// Выделяем память для ASN буфера параметров алгоритма
pbAlgParamASN = (PBYTE)STYXMALLOC(cbAlgParamASN);
if (NULL == pbAlgParamASN)
{
Status = NTE_NO_MEMORY;
goto Cleanup;
}
// Заполняем ASN буфер параметров алгоритма
pbAlgParamASN[0] = 0x30; // ASN.1 TRIPLET SEQ
pbAlgParamASN[1] = 4 + (BYTE)(cbParam1 + cbParam2); // ASN.1 TRIPLET SEQ LEN
pbAlgParamASN[2] = 0x06; // ASN.1 TRIPLET OBJ
pbAlgParamASN[3] = (BYTE)cbParam1; // ASN.1 TRIPLET OBJ LEN
SxH_GetOIDoctets_fromGS01PubParamID(dwPubParamId, pbAlgParamASN + 4, &cbParam1);
pbAlgParamASN[4 + cbParam1] = 0x06; // ASN.1 TRIPLET OBJ
pbAlgParamASN[5 + cbParam1] = (BYTE)cbParam2; // ASN.1 TRIPLET OBJ LEN
SxH_GetOIDoctets_fromSBoxID(dwEncParamId, pbAlgParamASN + 6 + cbParam1, &cbParam2);
// Заполняе указатель OID'а алгоритма
szAlgOID = szOID_OS_A2;
*ppbKeyBufASN = pbKeyBufASN;
*pcbKeyBufASN = cbKeyBufASN;
*ppbAlgParamASN = pbAlgParamASN;
*pcbAlgParamASN = cbAlgParamASN;
*pszAlgOID = szAlgOID;
// Сбрасываем указатели чтобы не освобождать память буферов при выходе
pbKeyBufASN = NULL;
pbAlgParamASN = NULL;
Cleanup:
if (NULL != pbKeyBufASN) STYXFREE(pbKeyBufASN);
if (NULL != pbAlgParamASN) STYXFREE(pbAlgParamASN);
return Status;
}