corePKCS11 Sign And Verify Demo
Introduction
This demo is the fourth in the corePKCS11 demo series. It introduces the section of the PKCS #11 API that is used to sign
messages and verify the signature of messages. The PKCS #11 standard can be found
here.
The corePKCS11 demo projects use the
FreeRTOS Windows port, so they can be built and evaluated with the
free Community version
of Visual Studio on Windows without the need for any particular MCU hardware.
The set of functions presented in this demo are categorized as:
- Object Management Functions
- Signing and MACing Functions
Source Code Organization
The Visual Studio solution for the PKCS #11 based mutual authentication demo is called
pkcs11_demos.sln
and is located in the
FreeRTOS\FreeRTOS-Plus\Demo\corePKCS11_Windows_Simulator\
directory of the main FreeRTOS download.
Click to enlarge
Configuring the Demo Project
To configure the demo project, set configPKCS11_SIGN_AND_VERIFY_DEMO
to 1 in
pkcs11_demo_config.h
. This is enabled by default. Once you complete this, the demo can be run, there is
no other configuration required for this demo.
Building the Demo Project
The demo project uses the
free community edition of Visual Studio.
- Open the
FreeRTOS\FreeRTOS-Plus\Demo\corePKCS11_Windows_Simulator\pkcs11_demos.sln
Visual Studio solution file from within the Visual Studio IDE.
- Select 'build solution' from the IDE's 'build' menu.
Functionality
The entry point for this demo is vPKCS11SignVerifyDemo
.
Note that this demo requires the public and private key pair created by the prvObjectGeneration
function in the
objects demo.
The demo will use this key pair to sign a message's digest. (See the Mechanisms and Digests demo for how to create a digest.)
The demo will also introduce some helpful functions, found in the "core_pkcs11.h" header file, that can be used to streamline
some of the functionality demonstrated in the previous demos.
The first step is to find the object handles for the private and public keys that were generated in the Objects demo.
Finding the proper object handles
xResult = xFindObjectWithLabelAndClass( hSession,
pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS,
CKO_PRIVATE_KEY,
&xPrivateKeyHandle );
configASSERT( xResult == CKR_OK );
configASSERT( xPrivateKeyHandle != CK_INVALID_HANDLE );
xResult = xFindObjectWithLabelAndClass( hSession,
pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS,
CKO_PRIVATE_KEY,
&xPublicKeyHandle );
configASSERT( xResult == CKR_OK );
configASSERT( xPublicKeyHandle != CK_INVALID_HANDLE );
Now that the object handles have been found, they can be used to sign a message digest and verify the signature. A private
key should always be protected because it can be used to sign a message, which allows the recipient to verify that the holder of the
private key was really the one who wrote the message. Anyone who has a public key generated from the private key, and uses it to
validate a message, must be able to assume that it is, in fact, a valid message from a known sender.
Creating a signature
xResult = pxFunctionList->C_SignInit( hSession,
&xMechanism,
xPrivateKeyHandle );
configASSERT( xResult == CKR_OK );
xResult = pxFunctionList->C_Sign( hSession,
xDigestResult,
pkcs11SHA256_DIGEST_LENGTH,
xSignature,
&xSignatureLength );
configASSERT( xResult == CKR_OK );
configASSERT( xSignatureLength == pkcs11ECDSA_P256_SIGNATURE_LENGTH );
The next step is to use the public key to make sure the PKCS #11 stack can trust that the message we received was from the sender. (The public key was derived from the private key that was used to create the message signature.) This will be done by using the PKCS #11 stack to verify the buffer that contains the signature.
Verifying a signature
xResult = pxFunctionList->C_VerifyInit( hSession,
&xMechanism,
xPublicKeyHandle );
configASSERT( xResult == CKR_OK );
xResult = pxFunctionList->C_Verify( hSession,
xDigestResult,
pkcs11SHA256_DIGEST_LENGTH,
xSignature,
xSignatureLength );
if( xResult == CKR_OK )
{
configPRINTF( ( "The signature of the digest was verified with the" \
" public key and can be trusted.\r\n" ) );
} else
{
configPRINTF( ( "Unable to verify the signature with the given public" \
" key, the message cannot be trusted.\r\n" ) );
}
How to Verify the signature in the terminal
The demo will output the contents of the signature buffer, and the hex format of the public key that can be used to
verify the signature.
Extracting the public key
Follow these steps to export the public key from the binary file it is contained in.
- Export the public key as hex bytes and print the hex representation of the public key. The demo will print the hex
bytes to the console.
- Create an empty text file called "
DevicePublicKeyAsciiHex.txt
".
- Copy and paste the hex value of the public key into this text file.
- Convert the hex file to binary using the xxd tool:
$ xxd -r -ps DevicePublicKeyAsciiHex.txt DevicePublicKeyDer.bin
xxd will take a text file that contains hex data and output a binary of the hex in the file. See
"$ man xxd
" for more information about xxd.
- Convert the binary encoding of the public key to PEM format:
$ openssl ec -inform der -in DevicePublicKeyDer.bin -pubin -pubout -outform pem -out public_key.pem
We now have extracted the public key and can use it to verify signatures generated by the PKCS #11 stack.
Extracting the signature
- Create an empty text file called "
signature.txt
".
- Copy and paste the signature buffer that was written to the console by the demo.
- Convert the signature to a binary format.
$ xxd -r -ps signature.txt signature.bin
WARNING: Running the object generation demo will create a new key pair and make it
necessary to redo these steps!
Verifying the Signature using OpenSSL
OpenSSL can be used to verify that the signature is trustworthy, and that the PKCS #11 stack is behaving as expected. OpenSSL is a
widely used crytpo kit that provides much helpful functionality. The command below uses the extracted public key to verify
the binary signature created by the PKCS #11 stack.
$ openssl dgst -sha256 -verify public_key.pem -signature signature.bin msg.txt
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.