...
Code Block | ||||
---|---|---|---|---|
| ||||
CK_OBJECT_CLASS ocPrivKey = CKO_PRIVATE_KEY; CK_UTF8CHAR PrivKeyLabel[] = { "GOST Private Key" }; CK_BYTE KeyPairID[] = { "GOST keypair" }; CK_KEY_TYPE keyTypeGostR3410 = CKK_GOSTR3410; // Для закрытого ключа длиной 256 бит CK_KEY_TYPE keyTypeGostR3410_512 = CKK_GOSTR3410_512; // Для закрытого ключа длиной 512 бит CK_BBOOL bTrue = CK_TRUE; /* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(256) */ CK_BYTE parametersGostR3410_2012_256[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 }; /* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(512) */ CK_BYTE parametersGostR3410_2012_512[] = { 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02, 0x01, 0x02, 0x01 }; /* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(256) */ CK_BYTE parametersGostR3411_2012_256[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x02 }; /* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(512) */ CK_BYTE parametersGostR3411_2012_512[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03 }; CK_ATTRIBUTE GOST34_10_2012_256_PrivateKey[] = { // Шаблон для ключа длиной 256 бит { CKA_CLASS, &ocPrivKey, sizeof(ocPrivKey)}, // Объект закрытого ключа { CKA_LABEL, &PrivKeyLabel, sizeof(PrivKeyLabel) - 1}, // Метка ключа { CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, // Идентификатор ключевой пары #1 (должен совпадать у открытого и закрытого ключей) { CKA_KEY_TYPE, &keyTypeGostR3410, sizeof(keyTypeGostR3410)}, // Тип ключа { CKA_TOKEN, &bTrue, sizeof(bTrue)}, // Ключ является объектом токена { CKA_PRIVATE, &bTrue, sizeof(bTrue)}, // Ключ доступен только после авторизации на токене { CKA_DERIVE, &bTrue, sizeof(bTrue)}, // Ключ поддерживает деривацию (из него могут быть получены другие ключи) { CKA_GOSTR3410_PARAMS, parametersGostR3410_2012_256, sizeof(parametersGostR3410_2012_256)}, // Параметры алгоритма { CKA_GOSTR3411_PARAMS, parametersGostR3411_2012_256, sizeof(parametersGostR3411_2012_256)} // Параметры алгоритма ГОСТ Р 34.11-2012(256) }; CK_ATTRIBUTE GOST34_10_2012_512_PrivateKey[] = { // Шаблон для ключа длиной 512 бит { CKA_CLASS, &ocPrivKey, sizeof(ocPrivKey)}, // Объект закрытого ключа { CKA_LABEL, &PrivKeyLabel, sizeof(PrivKeyLabel) - 1}, // Метка ключа { CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, // Идентификатор ключевой пары #1 (должен совпадать у открытого и закрытого ключей) { CKA_KEY_TYPE, &keyTypeGostR3410_512, sizeof(keyTypeGostR3410)_512)}, // Тип ключа { CKA_TOKEN, &bTrue, sizeof(bTrue)}, // Ключ является объектом токена { CKA_PRIVATE, &bTrue, sizeof(bTrue)}, // Ключ доступен только после авторизации на токене { CKA_DERIVE, &bTrue, sizeof(bTrue)}, // Ключ поддерживает деривацию (из него могут быть получены другие ключи) { CKA_GOSTR3410_PARAMS, parametersGostR3410_2012_512, sizeof(parametersGostR3410_2012_512)}, // Параметры алгоритма { CKA_GOSTR3411_PARAMS, parametersGostR3411_2012_512, sizeof(parametersGostR3411_2012_512)} // Параметры алгоритма ГОСТ Р 34.11-2012(512) }; |
...
Code Block | ||||
---|---|---|---|---|
| ||||
CK_OBJECT_CLASS ocPubKey = CKO_PUBLIC_KEY; CK_UTF8CHAR PubKeyLabel[] = { "GOST Public Key" }; CK_BYTE KeyPairID[] = { "GOST keypair" }; CCKCK_KEY_TYPE keyTypeGostR3410 = CKK_GOSTR3410; // Для закрытого ключа длиной 256 бит CK_KEY_TYPE keyTypeGostR3410_512 = CKK_GOSTR3410_512; // Для закрытого ключа длиной 512 бит CK_BBOOL bTrue = CK_TRUE; CK_BBOOL bFalse = CK_FALSE; /* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(256) */ CK_BYTE parametersGostR3410_2012_256[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01 }; /* Набор параметров КриптоПро A алгоритма ГОСТ Р 34.10-2012(512) */ CK_BYTE parametersGostR3410_2012_512[] = { 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02, 0x01, 0x02, 0x01 }; /* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(256) */ CK_BYTE parametersGostR3411_2012_256[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x02 }; /* Набор параметров КриптоПро алгоритма ГОСТ Р 34.11-2012(512) */ CK_BYTE parametersGostR3411_2012_512[] = { 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03 }; CK_ATTRIBUTE GOST34_10_2012_256_PublicKey[] = { // Шаблон для открытого ключа, соответствуюзегосоответствующего закрытому длиной 256 бит { CKA_CLASS, &ocPubKey, sizeof(ocPubKey)}, // Объект открытого ключа { CKA_LABEL, &PubKeyLabel, sizeof(PubKeyLabel) - 1}, // Метка ключа { CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, // Идентификатор ключевой пары { CKA_KEY_TYPE, &keyTypeGostR3410, sizeof(keyTypeGostR3410)}, // Тип ключа { CKA_TOKEN, &bTrue, sizeof(bTrue)}, // Ключ является объектом токена { CKA_PRIVATE, &bFalse, sizeof(bFalse)}, // Ключ доступен без авторизации на токене { CKA_DERIVE, &bTrue, sizeof(bTrue)}, // Ключ поддерживает деривацию (из него могут быть получены другие ключи) { CKA_GOSTR3410_PARAMS, paramsGostR3410parametersGostR3410_2012_256, sizeof(paramsGostR3410parametersGostR3410_2012_256)}, // Параметры алгоритма { CKA_GOSTR3411_PARAMS, paramsGostR3411parametersGostR3411_2012_256, sizeof(paramsGostR3411parametersGostR3411_2012_256)} // Параметры алгоритма }; CK_ATTRIBUTE GOST34_10_2012_512_PublicKey[] = { // Шаблон для открытого ключа, соответствуюзегосоответствующего закрытому длиной 512бит { CKA_CLASS, &ocPubKey, sizeof(ocPubKey)}, // Объект открытого ключа { CKA_LABEL, &PubKeyLabel, sizeof(PubKeyLabel) - 1}, // Метка ключа { CKA_ID, &KeyPairID, sizeof(KeyPairID) - 1}, // Идентификатор ключевой пары { CKA_KEY_TYPE, &keyTypeGostR3410_512, sizeof(keyTypeGostR3410_512)}, // Тип ключа { CKA_TOKEN, &bTrue, sizeof(bTrue)}, // Ключ является объектом токена { CKA_PRIVATE, &bFalse, sizeof(bFalse)}, // Ключ доступен без авторизации на токене { CKA_DERIVE, &bTrue, sizeof(bTrue)}, // Ключ поддерживает деривацию (из него могут быть получены другие ключи) { CKA_GOSTR3410_PARAMS, parametersGostR3410_2012_512, sizeof(parametersGostR3410_2012_512)}, // Параметры алгоритма { CKA_GOSTR3411_PARAMS, parametersGostR3411_2012_512, sizeof(parametersGostR3411_2012_512)} // Параметры алгоритма ГОСТ Р 34.11-2012(512) }; |
...
Code Block | ||||
---|---|---|---|---|
| ||||
/* Вычисление размера массива */ #define arraysize(a) (sizeof(a)/sizeof(a[0])) CK_MECHANISM gostR3410_256KeyPairGenMech = { CKM_GOSTR3410_KEY_PAIR_GEN, NULL_PTR, 0 }; // Механизм генерации ключевой пары ГОСТ Р 34.10-2012(256) CK_MECHANISM gostR3410_512KeyPairGenMech = { CKM_GOSTR3410_512_KEY_PAIR_GEN, NULL_PTR, 0 }; // Механизм генерации ключевой пары ГОСТ Р 34.10-2012(512) */ CK_OBJECT_HANDLE hPublicKey_256 = NULL_PTR; // Хэндл открытого ключа CK_OBJECT_HANDLE hPrivateKey_256 = NULL_PTR; // Хэндл закрытого ключа CK_OBJECT_HANDLE hPublicKey_512 = NULL_PTR; // Хэндл открытого ключа CK_OBJECT_HANDLE hPrivateKey_512 = NULL_PTR; // Хэндл закрытого ключа ... printf("Generating 256 bit key pair"); rv = pFunctionList->C_GenerateKeyPair(hSession, // Хэндл открытой сессии &gostR3410_256KeyPairGenMech, // Используемый механизм генерации ключевой &gostR3410KeyPairGenMech, // Используемый механизм генерации ключевой пары GOST34_10_2012_256_PublicKey, пары GOST34_10_2012_256_PublicKey, // Шаблон открытого ключа arraysize(GOST34_10_2012_256_PublicKey), // Размер шаблона открытого ключа GOST34_10_2012_256_PrivateKey, // Шаблон закрытого ключа arraysize(GOST34_10_2012_256_PrivateKey), // Размер шаблона закрытого ключа &hPublicKey_256, &hPublicKey_256, // Хэндл открытого ключа &hPrivateKey_256); // Хэндл закрытого ключа if (rv != CKR_OK) printf(" -> Failed\n"); else printf(" -> OK\n"); printf("Generating 512 bit key pair"); rv = pFunctionList->C_GenerateKeyPair(hSession, // Хэндл открытой сессии &gostR3410_512KeyPairGenMech, // Используемый механизм генерации ключевой пары GOST34_10_2012_512_PublicKey, // Шаблон GOST34_10_2012_512_PublicKey, // Шаблон открытого ключа открытого ключа arraysize(GOST34_10_2012_512_PublicKey), // Размер шаблона открытого ключа GOST34_10_2012_512_PrivateKey, // Шаблон закрытого ключа arraysize(GOST34_10_2012_512_PrivateKey), // Размер шаблона закрытого ключа &hPublicKey_512, // Хэндл открытого ключа &hPrivateKey_512); // Хэндл закрытого ключа if (rv &hPublicKey_512, // Хэндл открытого ключа &hPrivateKey_512); // Хэндл закрытого ключа if (rv != CKR_OK!= CKR_OK) printf(" -> Failed\n"); else printf(" -> OK\n"); |
...
Code Block | ||||
---|---|---|---|---|
| ||||
CK_OBJECT_CLASS ocSecKey = CKO_SECRET_KEY; CK_UTF8CHAR SecKeyLabel[] = {"GOST Secret Key"}; CK_BYTE SecKeyID[] = {"GOST Secret Key"}; CK_KEY_TYPE KeyType = CKK_GOST28147; CK_BBOOL bTrue = CK_TRUE; CK_BBOOL bFalse = CK_FALSE; /* Набор параметров КриптоПро A алгоритма ГОСТ 28147-89 */ CK_BYTE GOST28147params[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 }; CK_ATTRIBUTE attrGOST28147_89SecKey[] = { { CKA_CLASS, &ocSeckeyocSecKey, sizeof(ocSeckeyocSecKey)}, // Объект секретного ключа ГОСТ 28147-89 { CKA_LABEL, &SecKeyLabel, sizeof(SecKeyLabel) - 1}, // Метка ключа { CKA_ID, &SecKeyID, sizeof(SecKeyID) - 1}, // Идентификатор ключа { CKA_KEY_TYPE, &KeyType, sizeof(KeyType)}, // Тип ключа { CKA_ENCRYPT, &bTrue, sizeof(bTrue)}, // Ключ предназначен для зашифрования { CKA_DECRYPT, &bTrue, sizeof(bTrue)}, // Ключ предназначен для расшифрования { CKA_TOKEN, &bTrue, sizeof(bTrue)}, // Ключ является объектом токена { CKA_PRIVATE, &bFalse, sizeof(bFalse)}, // Ключ доступен без авторизации на токене { CKA_GOST28147_PARAMS, GOST28147params, sizeof(GOST28147params)} // Параметры алгоритма }; |
...
Для выработки сеансового ключ (CEK) в оперативной памяти токена, зашифрованного на KEK с имитовставкой CEK, необходимо использовать функцию расширения C_EX_WrapKey()
.
Параметры механизма согласования ключей задаются отдельной структурой типа CKCKM_GOSTR3410_2012_DERIVE _PARAMS, которая содержит:
...
задаются байтовым массивом, который имеет следующую структуру:
- 4 байта (little-endian, т.е. младшие байты сначала) представляют собой значение KDF. Значение определяет механизм диверсификации:
- CKD_NULL - нет диверсификации
- CKM_KDF_4357
- CKD_CPDIVERSIFY_KDF
- CKM_KDF_GOSTR3411_2012_256
- 4 байта (little-endian) задают длину открытого ключа в байтах. (64 либо 128)
- открытый ключ (n-байтовый вектор в little-endian), длина которого определена предыдущим полем
- 4 байта (little-endian) задают длину UKM (от 8 байт )
- UKM (n-байтовый вектор в little-endian) , длина определена выше
...
- .
Пример выработки общего ключа парной связи по алгоритму VKO GOST R 34.10-2012
Code Block | ||||
---|---|---|---|---|
| ||||
/* Размер синхропосылки в байтах */ #define UKM_LENGTH 8 #define DERIVE_PARAMS_256_LENGTH 84 /************************************************************************* * Параметры для выработки ключа обмена по схеме VKO GOST R 34.10-2012-256* * Содержат в себе данные по диверсификации ключа, открытый ключ и UKM * *************************************************************************/ CK_BYTE deriveParameters2012_256[DERIVE_PARAMS_256_LENGTH] = { 0x00, }; const CK_ULONG keyLengthOffset = 4; // Смещение длины ключа в массиве const CK_ULONG publicKeyValueOffset = 8; // Смещение значения ключа в массиве const CK_ULONG ukmLengthOffset = 72; // Смещение длины UKM в массиве const CK_ULONG ukmDataOffset = 76; // Смещение UKM в массиве /************************************************************************* * Функция записи четырёхбайтного значения длины в буфер * *************************************************************************/ void ulongToBuffer(CK_BYTE_PTR buffer, CK_ULONG value) { buffer[0] = value & 0xFF; buffer[1] = (value >> 8) & 0xFF; buffer[2] = (value >> 16) & 0xFF; buffer[3] = (value >> 24) & 0xFF; } /* Механизм выработки ключа обмена по алгоритму VKO GOST R 34.10-2012 */ CK_MECHANISM gostR3410_12DerivationMech = { CKM_GOSTR3410_12_DERIVE, NULL_PTR, 0 }; /* Значение открытого ключа получателя */ CK_BYTE cbPubRecipientKey[] = { 0xFF, FF0x8D, 8D0xAB, AB0x7F, 7F0x1C, 1C0x0B, 0B0x74, 740xA5, A5 AD0xAD, 7F0x7F, 0B0x0B, 5F0x5F, 8D0x8D, 5B0x5B, 3C0x3C, 44 0x44, 0x58, 0x37, 0x98, 0xC9, 580x25, 370x86, 980x40, C90x7E, 250xEC, 860x6E, 400xAF, 7E EC0x00, 6E0xCB, AF0x44, 00 CB 44 65 A5 0x65, 0xA5, 0x22, 0x9A, 0x53, 0x56, 220x32, 9A0x97, 530x35, 560x80, 320x99, 970xCA, 350x1E, 800x17, 990x21, CA0x3A, 1E 17 21 3A 96 0E 0x96, 0x0E, 0x21, 0xFB, 0xC6, 0x0F, 0x25, 0x5B, 0x5D, 0x99, 210x4E, FB0xC4, C60x5C, 0F0x42, 250x08, 5B0x7D, 5D 99 4E C4 5C 42 08 7D 06 040x06, 0x04 }; CK_OBJECT_CLASS ocSecKey = CKO_SECRET_KEY; CK_UTF8CHAR DerivedKeyLabel[] = { "Derived Key" }; CK_BYTE SecKeyID[] = { "GOST Secret Key" }; CK_KEY_TYPE KeyType = CKK_GOST28147; CK_BBOOL bTrue = CK_TRUE; CK_BBOOL bFalse = CK_FALSE; /* Шаблон для создания общего ключа */ CK_ATTRIBUTE attrGOST28147DerivedKey[] = { { CKA_CLASS, &ocSeckeyocSecKey, sizeof(ocSeckeyocSecKey)}, // Объект секретного ключа ГОСТ 28147-89 { CKA_LABEL, &DerivedKeyLabel, sizeof(DerivedKeyLabel) - 1}, // Метка ключа { CKA_KEY_TYPE, &KeyType, sizeof(KeyType)}, // Тип ключа { CKA_TOKEN, &bFalse, sizeof(bFalse)}, // Ключ является объектом сессии { CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, // Ключ может быть изменен после создания { CKA_PRIVATE, &bFalse, sizeof(bFalse)}, // Ключ доступен без авторизации { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue)}, // Ключ может быть извлечен и зашифрован { CKA_SENSITIVE, &bFalse, sizeof(bFalse)} // Ключ не может быть извлечен в открытом виде }; CK_ATTRIBUTE attrDerivedKeyValue = { CKA_VALUE, NULL_PTR, 0 }; // Структура данных типа CK_ATTRIBUTE для хранения значения атрибута CKA_VALUE CK_BYTE ukm[UKM_LENGTH]; // Буфер, содержащий UKM CK_OBJECT_HANDLE hDerivedKey_1 = NULL_PTR; // Хэндл выработанного на стороне отправителя общего ключа CK_OBJECT_HANDLE hObject, ; // Хэндл объекта ... /************************************************************************* * Установить Поместитьпараметры в структуруструктуре типа CK_MECHANISM параметры, необходимыеGOSTR3410_DERIVE_PARAMS * * для выработки ключа обмена * *************************************************************************/ ulongToBuffer(deriveParameters2012_256, CKM_KDF_GOSTR3411_2012_256); ulongToBuffer(deriveParameters2012_256 + keyLengthOffset, publicKeyValueSize); memcpy(deriveParameters2012_256 + publicKeyValueOffset, publicKeyValue, publicKeyValueSize); ulongToBuffer(deriveParameters2012_256 + ukmLengthOffset, ukmSize); memcpy(deriveParameters2012_256 + ukmDataOffset, ukm, ukmSize); gostR3410_12DerivationMech.pParameter = deriveParameters2012_256; gostR3410_12DerivationMech.ulParameterLen = sizeof(deriveParameters2012_256); /* Выработать общий ключ ГОСТ 28147-89 на основании закрытого ключа отправителя и открытого ключа получателя */ printf("C_DeriveKey"); rv = pFunctionList->C_DeriveKey(hSession, // Хэндл открытой с правами Пользователя сессии rv = pFunctionList->C_GenerateRandom(hSession, ukm, sizeof(ukm)); if (rv != CKR_OK) { printf(" -> Failed\n"); goto exit; } /************************************************************************* * Поместить в структуру типа CK_MECHANISM параметры, необходимые * * для &gostR3410_12DerivationMech, // Механизм ключевого обмена выработки ключа обмена hPrivateKey, // Хэндл закрытого ключа отправителя attrGOST28147DerivedKey, // Шаблон создания общего ключа arraysize(attrGOST28147DerivedKey), // Размер шаблона &hDerivedKey_1); // Хэндл общего выработанного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); goto exit; } printf(" -> OK\n"); /* Получить размер буфера для хранения значения атрибута CKA_VALUE*/ printf("Getting object value size* *************************************************************************/ ulongToBuffer(deriveParameters2012_256, CKM_KDF_GOSTR3411_2012_256); ulongToBuffer(deriveParameters2012_256 + keyLengthOffset, sizeof(cbPubRecipientKey)); memcpy(deriveParameters2012_256 + publicKeyValueOffset, cbPubRecipientKey, sizeof(cbPubRecipientKey)); ulongToBuffer(deriveParameters2012_256 + ukmLengthOffset, sizeof(ukm)); memcpy(deriveParameters2012_256 + ukmDataOffset, ukm, sizeof(ukm)); gostR3410_12DerivationMech.pParameter = deriveParameters2012_256; gostR3410_12DerivationMech.ulParameterLen = sizeof(deriveParameters2012_256); /* Выработать общий ключ ГОСТ 28147-89 на основании закрытого ключа отправителя и открытого ключа получателя */ printf("C_DeriveKey"); rv = pFunctionList->C_GetAttributeValueDeriveKey(hSession, // Хэндл открытой с правами Пользователя сессии &gostR3410_12DerivationMech, // Механизм ключевого обмена hPrivateKey, // Хэндл закрытого ключа отправителя attrGOST28147DerivedKey, // Шаблон создания общего ключа arraysize(attrGOST28147DerivedKey), // hDerivedKey_1,Размер шаблона &hDerivedKey); // Хэндл общего выработанного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); goto &attrDerivedKeyValue, exit; } printf(" -> OK\n"); /* Получить размер буфера для хранения значения атрибута CKA_VALUE*/ printf("Getting object value size"); rv = pFunctionList->C_GetAttributeValue(hSession, // Хэндл открытой с правами Пользователя сессии hDerivedKey, // Хэндл общего ключа &attrDerivedKeyValue, // Шаблон получения значения атрибута 1); // Количество атрибутов в шаблоне if (rv != CKR_OK) { printf(" -> Failed\n"); goto exit; } printf(" -> OK\n"); /* Выделить необходимое количество памяти для значения атрибута */ attrDerivedKeyValue.pValue = (CK_BYTE*)malloc(attrDerivedKeyValue.ulValueLen); if (attrDerivedKeyValue.pValue == NULL) { printf("Memory allocation for attrDerivedKeyValue failed! \n"); goto exit; } memset(attrDerivedKeyValue.pValue, 0, (attrDerivedKeyValue.ulValueLen * sizeof(CK_BYTE))); /* Получить значение общего ключа ГОСТ 28147-89 */ printf("Getting object value"); rv = pFunctionList->C_GetAttributeValue(hSession, // Хэндл открытой с правами Пользователя сессии hDerivedKey_1, rv = pFunctionList->C_GetAttributeValue(hSession, // Хэндл открытой с правами Пользователя сессии hDerivedKey, // Хэндл общего ключа &attrDerivedKeyValue, // Шаблон получения значения атрибута 1); // Количество атрибутов в шаблоне if (rv != CKR_OK) { printf(" -> Failed\n"); goto exit; } printf(" -> OK\n"); /* Распечатать буфер со значением общего ключа ГОСТ 28147-89 */ printf("Derived key data is:\n"); for (size_t i = 0; i < attrDerivedKeyValue.ulValueLen; i++) { printf("%02X ", ((CK_BYTE_PTR) attrDerivedKeyValue.pValue)[i]); if ((i + 1) % 8 == 0) printf("\n"); } exit: if (ckDeriveParams.pPublicData) { free(ckDeriveParams.pPublicData); ckDeriveParams.pPublicData = NULL_PTR; ckDeriveParams.ulPublicDataLen = 0; } if ((i + 1) % 8 == 0) printf("\n"); } exit: if (attrDerivedKeyValue.pValue) { free(attrDerivedKeyValue.pValue); attrDerivedKeyValue.pValue = NULL_PTR; attrDerivedKeyValue.ulValueLen = 0; } if (rv != CKR_OK) { pFunctionList->C_DestroyObject(hSession, hDerivedKey_1 hDerivedKey); hDerivedKey_1 = NULL_PTR; } if (rv != CKR_OK) printf("\nDeriving failed!\n\n"); else printf("Deriving has been completed successfully.\n\n"); |
Маскирование секретного ключа
...
В этом примере мы генерируем случайным образом сессионный ключ (CEK), а затем маскируем его общим ключом KEK, полученным из функции C_Derive()
.()
.
Code Block | ||||
---|---|---|---|---|
| ||||
/* Размер синхропосылки в байтах */
#define UKM_LENGTH 8
/* Размер симметричного ключа | ||||
Code Block | ||||
| ||||
/* Размер симметричного ключа ГОСТ 28147-89 в байтах */ #define GOST_28147_KEY_SIZE 0x20 /* Набор параметров КриптоПро A алгоритма ГОСТ 28147-89 */ CK_BYTE GOST28147params[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 }; /* Параметры для механизма маскирования/демаскирования */ CK_GOSTR3410_KEY_WRAP_PARAMS ckWrapParams = { GOST28147params; // Указатель параметры (OID) алгоритма ГОСТ 28147-89 (используетсяв только для C_WrapKey) // Если NULL_PTR, то используется CKA_GOSTR3411PARAMS. Для C_UnwrapKey должно быть NULL_PTR sizeof(GOST28147params); // Длина объектного идентификатора cbUKM; // Вектор инициализации (синхропосылки), если NULL_PTR -- используется случайное значение длиной 8 байт arraysize(cbUKM); // Длина синхропосылки (в байтах, кратно 8) hKey; // Хэндл ключа } байтах */ #define GOST_28147_KEY_SIZE 0x20 /* Набор параметров КриптоПро A алгоритма ГОСТ 28147-89 */ CK_BYTE GOST28147params[] = { 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01 }; CK_BYTE ukm[UKM_LENGTH] = {0x01, 0x02 ,0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; // Синхропосылка /* Механизм для маскирования/демаскирования ключа */ CK_MECHANISM ckmWrapMech = { CKM_GOST28147_KEY_WRAP, NULL_PTR, 0 }; CK_OBJECT_CLASS ocSecKey = CKO_SECRET_KEY; CK_UTF8CHAR WrapKeyLabel[] = { "GOST Wrapped Key" }; CK_UTF8CHAR UnWrapKeyLabel[] = { "GOST Unwrapped Key" }; CK_KEY_TYPE KeyType = CKK_GOST28147; CK_BBOOL bTrue = CK_TRUE; CK_BBOOL bFalse = CK_FALSE; /* Шаблон маскируемого ключа */ CK_ATTRIBUTE attrGOST28147KeyToWrap[] = { { CKA_CLASS, &ocSeckeyocSecKey, sizeof(ocSeckeyocSecKey)}, // Объект секретного ключа ГОСТ 28147-89 { CKA_LABEL, &WrapKeyLabel, sizeof(WrapKeyLabel) - 1 }, // Метка ключа { CKA_KEY_TYPE, &KeyType, sizeof(KeyType)}, // Тип ключа { CKA_TOKEN, &bFalse, sizeof(bFalse)}, // Ключ является объектом сессии { CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, // Ключ может быть изменен после создания { CKA_PRIVATE, &bFalse, sizeof(bFalse)}, // Ключ доступен без авторизации { CKA_VALUE, NULL_PTR, 0}, // Значение ключа { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue)}, // Ключ может быть извлечен и зашифрован { CKA_SENSITIVE, &bFalse, sizeof(bFalse)} // Ключ не может быть извлечен в открытом виде }; /* Шаблон демаскированного ключа */ CK_ATTRIBUTE attrGOST28147UnwrappedKey[] = { { CKA_CLASS, &ocSeckeyocSecKey, sizeof(ocSeckeyocSecKey)}, // Объект секретного ключа ГОСТ 28147-89 { CKA_LABEL, &UnWrapLabelGOSTUnWrapKeyLabel, sizeof(UnWrapLabelGOSTUnWrapKeyLabel) - 1}, // Метка ключа { CKA_KEY_TYPE, &KeyType, sizeof(KeyType)}, // Тип ключа { CKA_TOKEN, &bFalse, sizeof(bFalse)}, // Ключ является объектом сессии { CKA_MODIFIABLE, &bTrue, sizeof(bTrue)}, // Ключ может быть изменен после создания { CKA_PRIVATE, &bFalse, sizeof(bFalse)}, // Ключ доступен без авторизации { CKA_EXTRACTABLE, &bTrue, sizeof(bTrue)}, // Ключ может быть извлечен и зашифрован { CKA_SENSITIVE, &bFalse, sizeof(bFalse)} // Ключ не может быть извлечен в открытом виде }; /* Структура данных типа CK_ATTRIBUTE для хранения значения атрибута CKA_VALUE */ CK_ATTRIBUTE attrValue = { CKA_VALUE, NULL_PTR, 0 }; CK_OBJECT_HANDLE hDerivedKey_2; // Хэндл выработанного на стороне получателя общего ключа CK_BYTE_PTR pbtSessionKey = NULL_PTR; // Указатель на буфер, содержащий сессионный ключ CK_BYTE_PTR pbtWrappedKey = NULL_PTR; // Указатель на буфер, содержащий маскированный на стороне отправителя сессионный ключ CK_ULONG ulWrappedKeySize = 0; // Размер буфера со значением маскированного на стороне отправителя сессионного ключа, в байтах CK_BYTE_PTR pbtUnwrappedKey = NULL_PTR; // Указатель на буфер, содержащий демаскированный на стороне получателя сессионный ключ CK_ULONG ulUnwrappedKeySize = 0; // Размер буфера со значением демаскированного на стороне получателя сессионного ключа, в байтах CK_OBJECT_HANDLE hTempKey = NULL_PTR; // Хэндл ключа, который будет маскироваться/демаскироваться ... /*Установить параметры в структуре типа CK_MECHANISM /*Установить синхропосылку для маскирования ключа*/ ckmWrapMech.ulParameterLen = 8sizeof(ukm); GenerateRandomData(ckmWrapMech.ulParameterLen,pParameter (PBYTE *)&ckmWrapMech.pParameter)= ukm; /* Заполнить шаблон сессионного ключа случайными данными */ GenerateRandomData(GOST_28147_KEY_SIZE, &pbtSessionKey); for (int i = 0; i < arraysize(attrGOST28147KeyToWrap); i++) if (attrGOST28147KeyToWrap[i].type == CKA_VALUE) { attrGOST28147KeyToWrap[i].pValue = pbtSessionKey; attrGOST28147KeyToWrap[i].ulValueLen = GOST_28147_KEY_SIZE; break; } /************************************************************************* * Маскирование ключа * *************************************************************************/ /* Создать ключ, который будет маскирован */ printf("Creating the GOST 28147-89 key to wrap"); rv = pFunctionList->C_CreateObject(hSession, // Хэндл сессии, открытой с правами Пользователя attrGOST28147KeyToWrap, // Шаблон создаваемого ключа arraysize(attrGOST28147KeyToWrap), // Размер шаблона &hTempKey); // Хэндл созданного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); goto wrap_exit; } printf(" -> OK\n"); /* Получить размер буфера, содержащего значение маскированного ключа */ printf("Defining wrapping key size"); rv = pFunctionList->C_WrapKey(hSession, // Хэндл сессии, открытой с правами Пользователя &ckmWrapMech, // Механизм маскирования hDerivedKey_1, // Хэндл ключа, которым будет маскироваться ключ hTempKey, / Хэндл ключа, которым будет маскироваться ключ hTempKey, // Хэндл ключа, который будет маскирован NULL_PTR, // Указатель на буфер с маскированным ключом &ulWrappedKeySize); // Размер маскированного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); goto wrap_exit; } printf(" -> OK\n"); pbtWrappedKey = (CK_BYTE*)malloc(ulWrappedKeySize); if (pbtWrappedKey == NULL) { printf("Memory allocation for pbtWrappedKey failed! \n"); goto wrap_exit; } memset(pbtWrappedKey, 0, ulWrappedKeySize * sizeof(CK_BYTE)); /* Получить маскированный ключ на стороне отправителя */ printf("Wrapping key"); rv = pFunctionList->C_WrapKey(hSession, // Хэндл сессии, открытой с правами Пользователя &ckmWrapMech, // Механизм маскирования hDerivedKey_1, // Хэндл ключа, которым будет маскироваться ключ hTempKey, // Хэндл ключа, который будет маскирован pbtWrappedKey, // Указатель на буфер с маскированным ключом будет маскирован pbtWrappedKey, // Указатель на буфер с маскированным ключом &ulWrappedKeySize); // Размер маскированного ключа if (rv != CKR_OK) { printf(" -> Failed\n"); goto wrap_exit; } printf(" -> OK\n"); /* Распечатать буфер, содержащий маскированный ключ */ printf("Wrapped key data is:\n"); for (int i = 0; i < ulWrappedKeySize; i++) { printf("%02X ", pbtWrappedKey[i]); if ((i + 1) % 9 == 0) printf("\n"); } wrap_exit: if (hTempKey) { pFunctionList->C_DestroyObject(hSession, hTempKey); hTempKey = NULL_PTR; } if (rv == CKR_OK) printf("\nWrapping has been completed successfully.\n"); else { printf("\nWrapping failed!\n"); goto exit; } /************************************************************************* * Демаскирование ключа * *************************************************************************/ printf("Unwrapping key"); rv = pFunctionList->C_UnwrapKey(hSession, // Хэндл сессии, открытой с правами Пользователя &ckmWrapMech, // Механизм маскирования hDerivedKey_2, // Хэндл ключа, которым был маскирован ключ pbtWrappedKey, // Указатель на буфер с маскированным ключом ulWrappedKeySize, // Размер буфера с маскированным ключом // Размер буфера с маскированным ключом attrGOST28147UnwrappedKey, // Указатель на шаблон для демаскированного ключа arraysize(attrGOST28147UnwrappedKey), // Размер шаблона для демаскированного ключа &hTempKey); // Указатель на буфер с маскированным ключом if (rv != CKR_OK) { printf(" -> Failed\n"); goto unwrap_exit; } printf(" -> OK\n"); /* Получить буфер со значением демаскированного ключа */ printf("Getting unwrapped key value...\n"); /* Получить размер буфера для хранения значения атрибута CKA_VALUE */ printf("Getting object value size"); rv = pFunctionList->C_GetAttributeValue(hSession, // Хэндл сессии, открытой с правами Пользователя hTempKey, // Хэндл объекта, значение атрибутов которых требуется получить &attrValue, // Указатель на шаблон с атрибутами, значение которых требуется получить 1); // Количество строк в шаблоне if (rv != CKR_OK) { printf(" -> Failed\n"); goto unwrap_exit; } printf(" -> OK\n"); /* Выделить необходимое количество памяти для значения атрибута */ attrValue.pValue = (CK_BYTE*)malloc(attrValue.ulValueLen); if (attrValue.pValue == NULL) { printf("Memory allocation for attrValue failed! \n"); goto unwrap_exit; } memset(attrValue.pValue, 0, (attrValue.ulValueLen * sizeof(CK_BYTE))); /* Получить значение атрибута CKA_VALUE */ printf("Getting object value"); rv = pFunctionList->C_GetAttributeValue(hSession, // Хэндл сессии, открытой с правами Пользователя hTempKey, // Хэндл объекта, значение атрибутов которых требуется получить &attrValue, // Указатель на шаблон с атрибутами, значение которых требуется получить 1); // Количество строк в шаблоне if (rv != CKR_OK) { printf(" -> Failed\n"); goto unwrap_exit; } printf(" -> OK\n"); /* Распечатать буфер со значением демаскированного ключа */ printf("Unwrapped key data:\n"); for (int i = 0; i < attrValue.ulValueLen; i++) { printf("%02X ", ((CK_BYTE_PTR)attrValue.pValue)[i]); if ((i + 1) % 8 == 0) printf("\n"); } unwrap_exit: if (hTempKey) { pFunctionList->C_DestroyObject(hSession, hTempKey); hTempKey = NULL_PTR; } if (rv == CKR_OK) printf("Unwrapping has been completed successfully.\n\n"); else { printf("\nUnwrapping failed!\n\n"); goto exit; } /* Сравнить первоначальное значение сессионного ключа со значением демаскированного ключа */ if ((ulUnwrappedKeySize != GOST_28147_KEY_SIZE) || (memcmp(pbtSessionKey, attrValue.pValue, GOST_28147_KEY_SIZE) != 0)) printf("\nThe unwrapped key is not equal to the session key!\n"); else printf("The unwrapped key is equal to the session key.\n"); exit: printf("Finish"); |
Вычисление значения хеш-функции
...
Подпись данных отдельными механизмами хеширования и подписи
...
Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 отдельными механизмами хеширования и подписи для всех устройств Рутокен
...
При использовании совместного механизма и хеширование, и подпись выполняются функцией C_Sign()
. Сначала в функцию C_SignInit()
передается совместный механизм (например, CKM_GOSTR3410_WITH_GOSTR3411
), а затем в функцию C_Sign()
– сообщение.
Пример подписи данных по алгоритму ГОСТ Р 34.10-2012 совместным механизмом хеширования и подписи
...