1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5
6 #include "tls_context_pkcs11_options.h"
7
8 #include "crt.h"
9 #include "java_class_ids.h"
10
11 #include <aws/common/string.h>
12 #include <aws/io/pkcs11.h>
13 #include <aws/io/tls_channel_handler.h>
14
15 /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
16 #if UINTPTR_MAX == 0xffffffff
17 # if defined(_MSC_VER)
18 # pragma warning(push)
19 # pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to pointer */
20 # else
21 # pragma GCC diagnostic push
22 # pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
23 # pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
24 # endif
25 #endif
26
27 /* Contains aws_tls_ctx_pkcs11_options, plus values copied from
28 * the TlsContextPkcs11Options java object */
29 struct aws_tls_ctx_pkcs11_options_binding {
30 struct aws_tls_ctx_pkcs11_options options;
31
32 struct aws_string *user_pin;
33 struct aws_string *token_label;
34 struct aws_string *private_key_object_label;
35 struct aws_string *cert_file_path;
36 struct aws_string *cert_file_contents;
37
38 uint64_t slot_id;
39 };
40
aws_tls_ctx_pkcs11_options_from_java_destroy(struct aws_tls_ctx_pkcs11_options * options)41 void aws_tls_ctx_pkcs11_options_from_java_destroy(struct aws_tls_ctx_pkcs11_options *options) {
42 if (options == NULL) {
43 return;
44 }
45
46 struct aws_tls_ctx_pkcs11_options_binding *binding =
47 AWS_CONTAINER_OF(options, struct aws_tls_ctx_pkcs11_options_binding, options);
48
49 aws_pkcs11_lib_release(binding->options.pkcs11_lib);
50 aws_string_destroy_secure(binding->user_pin);
51 aws_string_destroy(binding->token_label);
52 aws_string_destroy(binding->private_key_object_label);
53 aws_string_destroy(binding->cert_file_path);
54 aws_string_destroy(binding->cert_file_contents);
55
56 aws_mem_release(aws_jni_get_allocator(), binding);
57 }
58
59 /* Helper for processing optional strings.
60 * If false is returned then a java exception has occurred */
s_read_optional_string(JNIEnv * env,jobject options_jni,jfieldID jstring_field_id,struct aws_string ** out_string,struct aws_byte_cursor * out_cursor)61 static bool s_read_optional_string(
62 JNIEnv *env,
63 jobject options_jni,
64 jfieldID jstring_field_id,
65 struct aws_string **out_string,
66 struct aws_byte_cursor *out_cursor) {
67
68 /* Check the field in TlsContextPkcs11Options.
69 * If it's NULL then we're all done, the user didn't set that optional string */
70 jstring field = (*env)->GetObjectField(env, options_jni, jstring_field_id);
71 if (field == NULL) {
72 return true;
73 }
74
75 struct aws_string *value = aws_jni_new_string_from_jstring(env, field);
76 if (value == NULL) {
77 return false;
78 }
79
80 *out_string = value;
81 *out_cursor = aws_byte_cursor_from_string(value);
82 return true;
83 }
84
aws_tls_ctx_pkcs11_options_from_java_new(JNIEnv * env,jobject options_jni)85 struct aws_tls_ctx_pkcs11_options *aws_tls_ctx_pkcs11_options_from_java_new(JNIEnv *env, jobject options_jni) {
86 struct aws_tls_ctx_pkcs11_options_binding *binding =
87 aws_mem_calloc(aws_jni_get_allocator(), 1, sizeof(struct aws_tls_ctx_pkcs11_options_binding));
88
89 /* pkcs11_lib is required */
90 jobject pkcs11_lib_jni = (*env)->GetObjectField(env, options_jni, tls_context_pkcs11_options_properties.pkcs11Lib);
91 if (pkcs11_lib_jni == NULL) {
92 aws_jni_throw_null_pointer_exception(env, "Pkcs11Lib is null");
93 goto error;
94 }
95
96 jlong pkcs11_lib_handle =
97 (*env)->CallLongMethod(env, pkcs11_lib_jni, crt_resource_properties.get_native_handle_method_id);
98 if (pkcs11_lib_handle == 0) {
99 aws_jni_throw_null_pointer_exception(env, "Pkcs11Lib.getNativeHandle() returned null");
100 goto error;
101 }
102
103 /* don't forget ref-counting to keep C object alive */
104 binding->options.pkcs11_lib = aws_pkcs11_lib_acquire((void *)pkcs11_lib_handle);
105
106 /* user_pin is optional String */
107 if (!s_read_optional_string(
108 env,
109 options_jni,
110 tls_context_pkcs11_options_properties.userPin,
111 &binding->user_pin,
112 &binding->options.user_pin)) {
113 goto error;
114 }
115
116 /* slot_id is optional Long */
117 jobject slot_id_jni = (*env)->GetObjectField(env, options_jni, tls_context_pkcs11_options_properties.slotId);
118 if (slot_id_jni != NULL) {
119 jlong slot_id_value = (*env)->CallLongMethod(env, slot_id_jni, boxed_long_properties.long_value_method_id);
120 if ((*env)->ExceptionCheck(env)) {
121 goto error;
122 }
123 binding->slot_id = (uint64_t)slot_id_value;
124 binding->options.slot_id = &binding->slot_id;
125 }
126
127 /* token_label is optional String */
128 if (!s_read_optional_string(
129 env,
130 options_jni,
131 tls_context_pkcs11_options_properties.tokenLabel,
132 &binding->token_label,
133 &binding->options.token_label)) {
134 goto error;
135 }
136
137 /* private_key_object_label is optional String */
138 if (!s_read_optional_string(
139 env,
140 options_jni,
141 tls_context_pkcs11_options_properties.privateKeyObjectLabel,
142 &binding->private_key_object_label,
143 &binding->options.private_key_object_label)) {
144 goto error;
145 }
146
147 /* cert_file_path is optional String */
148 if (!s_read_optional_string(
149 env,
150 options_jni,
151 tls_context_pkcs11_options_properties.certificateFilePath,
152 &binding->cert_file_path,
153 &binding->options.cert_file_path)) {
154 goto error;
155 }
156
157 /* binding->cert_file_contents is optional String */
158 if (!s_read_optional_string(
159 env,
160 options_jni,
161 tls_context_pkcs11_options_properties.certificateFileContents,
162 &binding->cert_file_contents,
163 &binding->options.cert_file_contents)) {
164 goto error;
165 }
166
167 if (!binding->cert_file_contents) {
168 if (!s_read_optional_string(
169 env,
170 options_jni,
171 tls_context_pkcs11_options_properties.certificateFileContents,
172 &binding->cert_file_contents,
173 &binding->options.cert_file_contents)) {
174 goto error;
175 }
176 }
177
178 /* success! */
179 return &binding->options;
180
181 error:
182 aws_tls_ctx_pkcs11_options_from_java_destroy(&binding->options);
183 return NULL;
184 }
185