xref: /aosp_15_r20/external/aws-crt-java/src/native/tls_context_pkcs11_options.c (revision 3c7ae9de214676c52d19f01067dc1a404272dc11)
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