Solving PKCS#11 Key Import Issues in AWS IoT Fleet Provisioning
Working on ESP32-C6 firmware for a smart locker controller, we ran into a stubborn CKR_ATTRIBUTE_VALUE_INVALID error when trying to import AWS claim certificates into PKCS#11 secure storage. After multiple failed attempts at parameter formatting, the solution came from understanding a fundamental design principle.
The Problem: Import vs. Generation
AWS IoT Fleet Provisioning uses a two-tier authentication system:
- Claim certificates: Temporary RSA credentials (external, provided by AWS)
- Device certificates: Permanent ECDSA credentials (internal, generated on-device)
Our ESP32 firmware needed to:
- Store AWS-provided claim certificates in PKCS#11
- Generate device keys internally using PKCS#11
- Use claim certs to request permanent device certificates from AWS
Simple enough, right?
The Persistent Error
E (4053) device_provisioning: β PKCS#11 error: 0x00000012 (CKR_ATTRIBUTE_VALUE_INVALID)
E (4063) device_provisioning: π‘ Failed to store RSA private key in secure storage
This CKR_ATTRIBUTE_VALUE_INVALID error appeared whenever we tried to import the external RSA claim keys into PKCS#11 storage.
Our Failed Attempts
1. RSA Parameter Formatting
We suspected the 2048-bit RSA parameters werenβt formatted correctly:
// Tried fixing public exponent alignment
unsigned char compactExponent[] = {0x01, 0x00, 0x01};
pubExpTemplate.pValue = compactExponent;
pubExpTemplate.ulValueLen = sizeof(compactExponent);
Result: Same error.
2. Minimal Templates
Maybe we were providing too many RSA parameters:
// Stripped down to only essential attributes
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass)},
{CKA_MODULUS, modulus, modulusLen},
{CKA_PRIVATE_EXPONENT, privateExponent, privateExponentLen}
};
Result: Same error.
3. Parameter Padding Investigation
We even examined the raw modulus and private exponent for alignment issues.
Result: Parameters looked correct, but same error persisted.
The Breakthrough Insight
The user made a crucial observation: βis that we can not push an object in PKCS#11 and the keys should be created inside of them?β
This hit the nail on the head. PKCS#11 is fundamentally designed for:
- Internal key generation (using
C_GenerateKeyPair) - Cryptographic operations on internally-managed keys
Itβs not designed for importing external keys, especially complex ones like RSA private keys with multiple parameters.
The Elegant Solution: Hybrid Approach
Instead of forcing external keys into PKCS#11, we implemented a hybrid approach:
Device Keys β PKCS#11 (Internal Generation)
// Generate ECDSA P-256 device keys internally in PKCS#11
CK_MECHANISM mechanism = {CKM_EC_KEY_PAIR_GEN, NULL, 0};
CK_OBJECT_HANDLE privateKey, publicKey;
result = C_GenerateKeyPair(session, &mechanism, publicKeyTemplate,
publicTemplateCount, privateKeyTemplate,
privateTemplateCount, &publicKey, &privateKey);
Claim Keys β MbedTLS Direct (External Import)
// Load claim credentials directly with MbedTLS
typedef struct {
mbedtls_x509_crt claim_cert;
mbedtls_pk_context claim_key;
bool initialized;
} claim_credentials_t;
// Parse directly without PKCS#11
mbedtls_x509_crt_parse(&credentials->claim_cert, cert_buffer, cert_len + 1);
mbedtls_pk_parse_key(&credentials->claim_key, key_buffer, key_len + 1,
NULL, 0, NULL, NULL);
Why This Works Better
1. Follows Design Intent
- PKCS#11 handles what itβs designed for: internal key generation
- MbedTLS handles external key parsing naturally
2. Better Security Model
- Device keys never leave secure hardware storage
- Claim keys are temporary and can be handled in regular memory
3. Cleaner Architecture
βββββββββββββββββββ βββββββββββββββββββ
β Claim Keys β β Device Keys β
β (External) β β (Internal) β
β β β β
β ββββββββββββββββ β βββββββββββββββ β
β β MbedTLS ββ β β PKCS#11 β β
β β Direct ββ β β Secure β β
β β Loading ββ β β Storage β β
β ββββββββββββββββ β βββββββββββββββ β
βββββββββββββββββββ βββββββββββββββββββ
β β
AWS Fleet Device Certificate
Provisioning Signing & Storage
The Fix in Action
Before: Persistent Errors
E (4053) device_provisioning: β PKCS#11 error: 0x00000012
E (4063) device_provisioning: Failed RSA parameter formatting attempts
E (4073) device_provisioning: CRT parameter issues
E (4083) device_provisioning: Multiple template variations failed
After: Clean Success
I (7050) device_provisioning: β
Claim certificate parsed successfully
I (7130) device_provisioning: β
Claim private key parsed successfully
I (7140) device_provisioning: π Key type: RSA (correct for AWS claim credentials)
I (7160) device_provisioning: π Claim credentials loaded successfully with MbedTLS!
Lessons Learned
1. Understand the Toolβs Purpose
PKCS#11 isnβt a general-purpose key storage system. Itβs a cryptographic token interface designed for hardware security modules and internal key generation.
2. Donβt Force Square Pegs into Round Holes
When a tool repeatedly resists your approach, step back and question whether youβre using it correctly.
3. Hybrid Approaches Are Often Better
Using the right tool for each job (PKCS#11 for secure generation, MbedTLS for external parsing) created a more robust solution than trying to make one tool do everything.
4. Security Models Matter
The hybrid approach actually improved our security posture:
- Device keys stay in hardware security
- Claim keys have appropriate (temporary) handling
Final Architecture
Our final AWS IoT Fleet Provisioning flow:
- WiFi Connection β Basic connectivity established
- PKCS#11 Init β Secure storage system ready
- Device Key Generation β ECDSA P-256 keys in secure storage
- Claim Credentials Loading β MbedTLS direct parsing
- MQTT Provisioning β Uses hybrid credential approach
- Certificate Exchange β Secure device certificate obtained
The key insight: Use each tool for what itβs designed to do, rather than trying to make one tool handle everything.
Impact
This solution eliminated the persistent CKR_ATTRIBUTE_VALUE_INVALID errors and created a more maintainable, secure architecture for ESP32 AWS IoT integration. The hybrid approach is now part of our standard IoT device provisioning pattern.