-
Notifications
You must be signed in to change notification settings - Fork 37
/
aes_wrapping.c
136 lines (115 loc) · 4.59 KB
/
aes_wrapping.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <common.h>
#include "aes_wrapping_common.h"
CK_RV aes_pkcs5_padding_wrapping(CK_SESSION_HANDLE session) {
unsigned char *hex_array = NULL;
CK_BYTE_PTR wrapped_key = NULL;
// Generate a wrapping key.
CK_OBJECT_HANDLE wrapping_key = CK_INVALID_HANDLE;
CK_RV rv = generate_aes_token_key_for_wrapping(session, 32, &wrapping_key);
if (rv != CKR_OK) {
fprintf(stderr, "Wrapping key generation failed: %lu\n", rv);
goto done;
}
// Generate keys to be wrapped.
CK_OBJECT_HANDLE rsa_public_key = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE rsa_private_key = CK_INVALID_HANDLE;
rv = generate_rsa_keypair(session, 2048, &rsa_public_key, &rsa_private_key);
if (rv != CKR_OK) {
fprintf(stderr, "RSA key generation failed: %lu\n", rv);
goto done;
}
// AES Key Wrap with PKCS #5 Padding.
// This algorithm is not compliant with the PKCS #11 standard.
// See first known issue under https://docs.aws.amazon.com/cloudhsm/latest/userguide/KnownIssues.html#ki-all
// There is also an alias option from vendor defined mechanisms:
// * CKM_CLOUDHSM_AES_KEY_WRAP_PKCS5_PAD
CK_MECHANISM mech = { CKM_CLOUDHSM_AES_KEY_WRAP_PKCS5_PAD, NULL, 0 };
// Determine how much space needs to be allocated for the wrapped key.
CK_ULONG wrapped_len = 0;
rv = aes_wrap_key(session, &mech, wrapping_key, rsa_private_key, NULL, &wrapped_len);
if (rv != CKR_OK) {
fprintf(stderr, "Could not determine size of wrapped key: %lu\n", rv);
goto done;
}
wrapped_key = malloc(wrapped_len);
if (NULL == wrapped_key) {
fprintf(stderr, "Could not allocate memory to hold wrapped key\n");
goto done;
}
// Wrap the key with PKCS #5 Padding.
rv = aes_wrap_key(session, &mech, wrapping_key, rsa_private_key, wrapped_key, &wrapped_len);
if (rv != CKR_OK) {
fprintf(stderr, "Could not wrap key: %lu\n", rv);
goto done;
}
// Display the hex string.
bytes_to_new_hexstring(wrapped_key, wrapped_len, &hex_array);
if (!hex_array) {
fprintf(stderr, "Could not allocate hex array\n");
goto done;
}
printf("Wrapped key: %s\n", hex_array);
// Unwrap the key back into the HSM to verify everything worked.
CK_OBJECT_HANDLE unwrapped_handle = CK_INVALID_HANDLE;
rv = aes_unwrap_key(session, &mech, wrapping_key, CKK_RSA, wrapped_key, wrapped_len, &unwrapped_handle);
if (rv != CKR_OK) {
fprintf(stderr, "Could not unwrap key: %lu\n", rv);
goto done;
}
printf("Unwrapped bytes as object %lu\n", unwrapped_handle);
done:
if (NULL != wrapped_key) {
free(wrapped_key);
}
if (NULL != hex_array) {
free(hex_array);
}
// The wrapping key is a token key, so we have to clean it up.
CK_RV cleanup_rv = funcs->C_DestroyObject(session, wrapping_key);
if (CKR_OK != cleanup_rv) {
fprintf(stderr, "Failed to delete wrapping key with rv: %lu\n", cleanup_rv);
}
return rv;
}
int main(int argc, char **argv) {
CK_RV rv;
CK_SESSION_HANDLE session;
int rc = EXIT_FAILURE;
struct pkcs_arguments args = {0};
if (get_pkcs_args(argc, argv, &args) < 0) {
return rc;
}
rv = pkcs11_initialize(args.library);
if (CKR_OK != rv) {
return rc;
}
rv = pkcs11_open_session(args.pin, &session);
if (CKR_OK != rv) {
return rc;
}
printf("Running AES wrap with PKCS #5 Padding...\n");
rv = aes_pkcs5_padding_wrapping(session);
if (CKR_OK != rv) {
return rc;
}
pkcs11_finalize_session(session);
return EXIT_SUCCESS;
}