0

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;
}
  • Take the [tour], read [Ask], and [MCVE]. What exactly does this piece of code do and how exactly does that differ from what you want it to do? Did you bother to search for the pkcs8 data structure](https://www.google.com/search?source=hp&ei=I0giW6qZMo-t0PEP7q6AuAE&q=pkcs8+data+structure&oq=pkcs8+data+structure&gs_l=psy-ab.3..33i160k1.1119.10869.0.11069.24.21.3.0.0.0.56.939.21.21.0....0...1c.1.64.psy-ab..0.24.944...0j0i22i30k1j33i21k1.0.LXO8Gw_qjs8)? – jwdonahue Jun 14 '18 at 10:51
  • I do not know how it should look like, because i dont know where and what to change, this is huge project with a lot of code, So I need some hint, from where should I start. Yes I already searched, and could not found any solution – Aziz Parpiyev Jun 14 '18 at 11:08

0 Answers0