1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5
6 #include "crt.h"
7
8 #include "aws_signing.h"
9 #include "credentials.h"
10 #include "http_request_utils.h"
11 #include "java_class_ids.h"
12
13 #include <jni.h>
14 #include <string.h>
15
16 #include <aws/auth/credentials.h>
17 #include <aws/auth/signable.h>
18 #include <aws/auth/signing.h>
19 #include <aws/auth/signing_result.h>
20 #include <aws/cal/ecc.h>
21 #include <aws/common/string.h>
22 #include <aws/http/request_response.h>
23 #include <aws/io/stream.h>
24
25 /* on 32-bit platforms, casting pointers to longs throws a warning we don't need */
26 #if UINTPTR_MAX == 0xffffffff
27 # if defined(_MSC_VER)
28 # pragma warning(push)
29 # pragma warning(disable : 4305) /* 'type cast': truncation from 'jlong' to 'jni_tls_ctx_options *' */
30 # else
31 # pragma GCC diagnostic push
32 # pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
33 # pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
34 # endif
35 #endif
36
37 struct s_aws_sign_request_callback_data {
38 JavaVM *jvm;
39 jobject java_signing_result_future;
40 jobject java_original_request;
41 jobject java_original_chunk_body;
42 jbyteArray java_previous_signature;
43 struct aws_http_headers *trailing_headers;
44 struct aws_input_stream *chunk_body_stream;
45 struct aws_http_message *native_request;
46 struct aws_signable *original_message_signable;
47 struct aws_byte_cursor previous_signature;
48
49 struct aws_signing_config_data signing_config_data;
50 };
51
aws_signing_config_data_clean_up(struct aws_signing_config_data * data,JNIEnv * env)52 void aws_signing_config_data_clean_up(struct aws_signing_config_data *data, JNIEnv *env) {
53
54 aws_string_destroy(data->region);
55 aws_string_destroy(data->service);
56 aws_string_destroy(data->signed_body_value);
57
58 if (data->java_sign_header_predicate) {
59 (*env)->DeleteGlobalRef(env, data->java_sign_header_predicate);
60 }
61 if (data->java_credentials_provider) {
62 (*env)->DeleteGlobalRef(env, data->java_credentials_provider);
63 }
64 aws_credentials_release(data->credentials);
65 }
66
s_cleanup_callback_data(struct s_aws_sign_request_callback_data * callback_data,JNIEnv * env)67 static void s_cleanup_callback_data(struct s_aws_sign_request_callback_data *callback_data, JNIEnv *env) {
68 if (callback_data == NULL || env == NULL) {
69 return;
70 }
71
72 if (callback_data->java_signing_result_future != NULL) {
73 (*env)->DeleteGlobalRef(env, callback_data->java_signing_result_future);
74 }
75
76 if (callback_data->java_original_request != NULL) {
77 (*env)->DeleteGlobalRef(env, callback_data->java_original_request);
78 }
79
80 if (callback_data->java_original_chunk_body != NULL) {
81 (*env)->DeleteGlobalRef(env, callback_data->java_original_chunk_body);
82 }
83
84 if (callback_data->native_request) {
85 aws_http_message_release(callback_data->native_request);
86 }
87
88 if (callback_data->original_message_signable) {
89 aws_signable_destroy(callback_data->original_message_signable);
90 }
91
92 if (callback_data->chunk_body_stream != NULL) {
93 aws_input_stream_destroy(callback_data->chunk_body_stream);
94 }
95 if (callback_data->trailing_headers != NULL) {
96 aws_http_headers_release(callback_data->trailing_headers);
97 }
98
99 if (callback_data->previous_signature.len > 0 && callback_data->java_previous_signature != NULL) {
100 aws_jni_byte_cursor_from_jbyteArray_release(
101 env, callback_data->java_previous_signature, callback_data->previous_signature);
102 }
103
104 if (callback_data->java_previous_signature != NULL) {
105 (*env)->DeleteGlobalRef(env, callback_data->java_previous_signature);
106 }
107
108 aws_signing_config_data_clean_up(&callback_data->signing_config_data, env);
109
110 aws_mem_release(aws_jni_get_allocator(), callback_data);
111 }
112
s_create_signed_java_http_request(JNIEnv * env,struct aws_http_message * native_request,jobject java_original_request)113 static jobject s_create_signed_java_http_request(
114 JNIEnv *env,
115 struct aws_http_message *native_request,
116 jobject java_original_request) {
117 jobject jni_body_stream =
118 (*env)->GetObjectField(env, java_original_request, http_request_properties.body_stream_field_id);
119
120 jobject http_request = aws_java_http_request_from_native(env, native_request, jni_body_stream);
121
122 if (jni_body_stream != NULL) {
123 (*env)->DeleteLocalRef(env, jni_body_stream);
124 }
125
126 return http_request;
127 }
128
s_complete_signing_exceptionally(JNIEnv * env,struct s_aws_sign_request_callback_data * callback_data,int error_code)129 static void s_complete_signing_exceptionally(
130 JNIEnv *env,
131 struct s_aws_sign_request_callback_data *callback_data,
132 int error_code) {
133
134 if (error_code == AWS_ERROR_SUCCESS) {
135 error_code = AWS_ERROR_UNKNOWN;
136 }
137
138 jobject crt_exception = aws_jni_new_crt_exception_from_error_code(env, error_code);
139
140 (*env)->CallBooleanMethod(
141 env,
142 callback_data->java_signing_result_future,
143 completable_future_properties.complete_exceptionally_method_id,
144 crt_exception);
145
146 aws_jni_check_and_clear_exception(env);
147 (*env)->DeleteLocalRef(env, crt_exception);
148 }
149
s_aws_complete_signing_result(JNIEnv * env,struct aws_signing_result * result,struct s_aws_sign_request_callback_data * callback_data,jobject java_signed_request)150 static void s_aws_complete_signing_result(
151 JNIEnv *env,
152 struct aws_signing_result *result,
153 struct s_aws_sign_request_callback_data *callback_data,
154 jobject java_signed_request) {
155 jbyteArray java_signature = NULL;
156 jobject java_signing_result = NULL;
157
158 struct aws_string *signature = NULL;
159 aws_signing_result_get_property(result, g_aws_signature_property_name, &signature);
160
161 /* Anonymous requests don't have a signature because they are not signed. */
162 if (signature != NULL) {
163 struct aws_byte_cursor signature_cursor = aws_byte_cursor_from_string(signature);
164 java_signature = aws_jni_byte_array_from_cursor(env, &signature_cursor);
165 }
166
167 java_signing_result = (*env)->NewObject(
168 env, aws_signing_result_properties.aws_signing_result_class, aws_signing_result_properties.constructor);
169 if ((*env)->ExceptionCheck(env) || java_signing_result == NULL) {
170 s_complete_signing_exceptionally(env, callback_data, AWS_ERROR_UNKNOWN);
171 goto done;
172 }
173
174 (*env)->SetObjectField(
175 env, java_signing_result, aws_signing_result_properties.signed_request_field_id, java_signed_request);
176 (*env)->SetObjectField(env, java_signing_result, aws_signing_result_properties.signature_field_id, java_signature);
177
178 (*env)->CallBooleanMethod(
179 env,
180 callback_data->java_signing_result_future,
181 completable_future_properties.complete_method_id,
182 java_signing_result);
183
184 /* I have no idea what we should do here... but the JVM really doesn't like us NOT calling this function after
185 we cross the barrier. */
186 AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
187
188 done:
189
190 if (java_signature != NULL) {
191 (*env)->DeleteLocalRef(env, java_signature);
192 }
193
194 if (java_signing_result != NULL) {
195 (*env)->DeleteLocalRef(env, java_signing_result);
196 }
197
198 if (java_signed_request != NULL) {
199 (*env)->DeleteLocalRef(env, java_signed_request);
200 }
201 }
202
s_aws_request_signing_complete(struct aws_signing_result * result,int error_code,void * userdata)203 static void s_aws_request_signing_complete(struct aws_signing_result *result, int error_code, void *userdata) {
204
205 struct s_aws_sign_request_callback_data *callback_data = userdata;
206
207 /********** JNI ENV ACQUIRE **********/
208 JNIEnv *env = aws_jni_acquire_thread_env(callback_data->jvm);
209 if (env == NULL) {
210 /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
211 return;
212 }
213
214 if (result == NULL || error_code != AWS_ERROR_SUCCESS) {
215 s_complete_signing_exceptionally(env, callback_data, error_code);
216 goto done;
217 }
218
219 if (aws_apply_signing_result_to_http_request(callback_data->native_request, aws_jni_get_allocator(), result)) {
220 s_complete_signing_exceptionally(env, callback_data, aws_last_error());
221 goto done;
222 }
223
224 jobject java_signed_request =
225 s_create_signed_java_http_request(env, callback_data->native_request, callback_data->java_original_request);
226 if (java_signed_request == NULL) {
227 s_complete_signing_exceptionally(env, callback_data, aws_last_error());
228 goto done;
229 }
230
231 s_aws_complete_signing_result(env, result, callback_data, java_signed_request);
232
233 done:;
234
235 JavaVM *jvm = callback_data->jvm;
236 s_cleanup_callback_data(callback_data, env);
237
238 aws_jni_release_thread_env(jvm, env);
239 /********** JNI ENV RELEASE **********/
240 }
241
s_aws_chunk_like_signing_complete(struct aws_signing_result * result,int error_code,void * userdata)242 static void s_aws_chunk_like_signing_complete(struct aws_signing_result *result, int error_code, void *userdata) {
243
244 struct s_aws_sign_request_callback_data *callback_data = userdata;
245
246 /********** JNI ENV ACQUIRE **********/
247 JNIEnv *env = aws_jni_acquire_thread_env(callback_data->jvm);
248 if (env == NULL) {
249 /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
250 return;
251 }
252
253 if (result == NULL || error_code != AWS_ERROR_SUCCESS) {
254 s_complete_signing_exceptionally(env, callback_data, error_code);
255 goto done;
256 }
257
258 s_aws_complete_signing_result(env, result, callback_data, NULL);
259
260 done:;
261
262 JavaVM *jvm = callback_data->jvm;
263 s_cleanup_callback_data(callback_data, env);
264
265 aws_jni_release_thread_env(jvm, env);
266 /********** JNI ENV RELEASE **********/
267 }
268
s_aws_chunk_signing_complete(struct aws_signing_result * result,int error_code,void * userdata)269 static void s_aws_chunk_signing_complete(struct aws_signing_result *result, int error_code, void *userdata) {
270 s_aws_chunk_like_signing_complete(result, error_code, userdata);
271 }
272
s_aws_trailing_headers_signing_complete(struct aws_signing_result * result,int error_code,void * userdata)273 static void s_aws_trailing_headers_signing_complete(struct aws_signing_result *result, int error_code, void *userdata) {
274 s_aws_chunk_like_signing_complete(result, error_code, userdata);
275 }
276
s_should_sign_header(const struct aws_byte_cursor * name,void * user_data)277 static bool s_should_sign_header(const struct aws_byte_cursor *name, void *user_data) {
278 struct aws_signing_config_data *callback_data = user_data;
279
280 /********** JNI ENV ACQUIRE **********/
281 JNIEnv *env = aws_jni_acquire_thread_env(callback_data->jvm);
282 if (env == NULL) {
283 /* If we can't get an environment, then the JVM is probably shutting down. Don't crash. */
284 return false;
285 }
286
287 jstring header_name = aws_jni_string_from_cursor(env, name);
288
289 bool result = (*env)->CallBooleanMethod(
290 env, callback_data->java_sign_header_predicate, predicate_properties.test_method_id, (jobject)header_name);
291 AWS_FATAL_ASSERT(!aws_jni_check_and_clear_exception(env));
292
293 (*env)->DeleteLocalRef(env, header_name);
294
295 aws_jni_release_thread_env(callback_data->jvm, env);
296 /********** JNI ENV RELEASE **********/
297
298 return result;
299 }
300
aws_build_signing_config(JNIEnv * env,jobject java_config,struct aws_signing_config_data * config_data,struct aws_signing_config_aws * config)301 int aws_build_signing_config(
302 JNIEnv *env,
303 jobject java_config,
304 struct aws_signing_config_data *config_data,
305 struct aws_signing_config_aws *config) {
306
307 jint jvmresult = (*env)->GetJavaVM(env, &config_data->jvm);
308 AWS_FATAL_ASSERT(jvmresult == 0);
309
310 config->config_type = AWS_SIGNING_CONFIG_AWS;
311 config->algorithm = (enum aws_signing_algorithm)(*env)->GetIntField(
312 env, java_config, aws_signing_config_properties.algorithm_field_id);
313 config->signature_type = (enum aws_signature_type)(*env)->GetIntField(
314 env, java_config, aws_signing_config_properties.signature_type_field_id);
315
316 jstring region = (jstring)(*env)->GetObjectField(env, java_config, aws_signing_config_properties.region_field_id);
317 if (region == NULL) {
318 AWS_ZERO_STRUCT(config->region);
319 } else {
320 config_data->region = aws_jni_new_string_from_jstring(env, region);
321 config->region = aws_byte_cursor_from_string(config_data->region);
322 }
323
324 jstring service = (jstring)(*env)->GetObjectField(env, java_config, aws_signing_config_properties.service_field_id);
325 if (service == NULL) {
326 AWS_ZERO_STRUCT(config->service);
327 } else {
328 config_data->service = aws_jni_new_string_from_jstring(env, service);
329 config->service = aws_byte_cursor_from_string(config_data->service);
330 }
331
332 int64_t epoch_time_millis = (*env)->GetLongField(env, java_config, aws_signing_config_properties.time_field_id);
333 aws_date_time_init_epoch_millis(&config->date, (uint64_t)epoch_time_millis);
334
335 jobject sign_header_predicate =
336 (*env)->GetObjectField(env, java_config, aws_signing_config_properties.should_sign_header_field_id);
337 if (sign_header_predicate != NULL) {
338 config_data->java_sign_header_predicate = (*env)->NewGlobalRef(env, sign_header_predicate);
339 AWS_FATAL_ASSERT(config_data->java_sign_header_predicate != NULL);
340
341 config->should_sign_header = s_should_sign_header;
342 config->should_sign_header_ud = config_data;
343 }
344
345 config->flags.use_double_uri_encode =
346 (*env)->GetBooleanField(env, java_config, aws_signing_config_properties.use_double_uri_encode_field_id);
347 config->flags.should_normalize_uri_path =
348 (*env)->GetBooleanField(env, java_config, aws_signing_config_properties.should_normalize_uri_path_field_id);
349 config->flags.omit_session_token =
350 (*env)->GetBooleanField(env, java_config, aws_signing_config_properties.omit_session_token_field_id);
351
352 jstring signed_body_value =
353 (jstring)(*env)->GetObjectField(env, java_config, aws_signing_config_properties.signed_body_value_field_id);
354 if (signed_body_value == NULL) {
355 AWS_ZERO_STRUCT(config->signed_body_value);
356 } else {
357 config_data->signed_body_value = aws_jni_new_string_from_jstring(env, signed_body_value);
358 config->signed_body_value = aws_byte_cursor_from_string(config_data->signed_body_value);
359 }
360
361 config->signed_body_header =
362 (*env)->GetIntField(env, java_config, aws_signing_config_properties.signed_body_header_field_id);
363
364 jobject provider =
365 (*env)->GetObjectField(env, java_config, aws_signing_config_properties.credentials_provider_field_id);
366 if (provider != NULL) {
367 config->credentials_provider =
368 (void *)(*env)->CallLongMethod(env, provider, crt_resource_properties.get_native_handle_method_id);
369 /* Keep the java object alive */
370 config_data->java_credentials_provider = (*env)->NewGlobalRef(env, provider);
371 AWS_FATAL_ASSERT(config_data->java_credentials_provider != NULL);
372 aws_jni_check_and_clear_exception(env);
373 }
374
375 jobject credentials = (*env)->GetObjectField(env, java_config, aws_signing_config_properties.credentials_field_id);
376 if (credentials != NULL) {
377 config_data->credentials = aws_credentials_new_from_java_credentials(env, credentials);
378 config->credentials = config_data->credentials;
379 }
380
381 config->expiration_in_seconds =
382 (uint64_t)(*env)->GetLongField(env, java_config, aws_signing_config_properties.expiration_in_seconds_field_id);
383
384 if (aws_jni_check_and_clear_exception(env)) {
385 return aws_raise_error(AWS_ERROR_HTTP_CALLBACK_FAILURE);
386 }
387
388 return AWS_OP_SUCCESS;
389 }
390
391 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSignRequest(JNIEnv * env,jclass jni_class,jobject java_http_request,jbyteArray marshalled_request,jobject java_signing_config,jobject java_signing_result_future)392 void JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSignRequest(
393 JNIEnv *env,
394 jclass jni_class,
395 jobject java_http_request,
396 jbyteArray marshalled_request,
397 jobject java_signing_config,
398 jobject java_signing_result_future) {
399
400 (void)jni_class;
401 aws_cache_jni_ids(env);
402
403 struct aws_allocator *allocator = aws_jni_get_allocator();
404 struct s_aws_sign_request_callback_data *callback_data =
405 aws_mem_calloc(allocator, 1, sizeof(struct s_aws_sign_request_callback_data));
406 if (callback_data == NULL) {
407 aws_jni_throw_runtime_exception(env, "Failed to allocated sign request callback data");
408 return;
409 }
410
411 jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
412 AWS_FATAL_ASSERT(jvmresult == 0);
413
414 callback_data->java_signing_result_future = (*env)->NewGlobalRef(env, java_signing_result_future);
415 AWS_FATAL_ASSERT(callback_data->java_signing_result_future != NULL);
416
417 callback_data->java_original_request = (*env)->NewGlobalRef(env, java_http_request);
418 AWS_FATAL_ASSERT(callback_data->java_original_request != NULL);
419
420 /* Build a native aws_signing_config_aws object */
421 struct aws_signing_config_aws signing_config;
422 AWS_ZERO_STRUCT(signing_config);
423
424 if (aws_build_signing_config(env, java_signing_config, &callback_data->signing_config_data, &signing_config)) {
425 aws_jni_throw_runtime_exception(env, "Failed to create signing configuration");
426 goto on_error;
427 }
428
429 jobject java_http_request_body_stream =
430 (*env)->GetObjectField(env, java_http_request, http_request_properties.body_stream_field_id);
431
432 callback_data->native_request =
433 aws_http_request_new_from_java_http_request(env, marshalled_request, java_http_request_body_stream);
434 if (callback_data->native_request == NULL) {
435 aws_jni_throw_runtime_exception(env, "Failed to create native http request from Java HttpRequest");
436 goto on_error;
437 }
438
439 callback_data->original_message_signable = aws_signable_new_http_request(allocator, callback_data->native_request);
440 if (callback_data->original_message_signable == NULL) {
441 aws_jni_throw_runtime_exception(env, "Failed to create signable from http request");
442 goto on_error;
443 }
444
445 /* Sign the native request */
446 if (aws_sign_request_aws(
447 allocator,
448 callback_data->original_message_signable,
449 (struct aws_signing_config_base *)&signing_config,
450 s_aws_request_signing_complete,
451 callback_data)) {
452 aws_jni_throw_runtime_exception(env, "Failed to initiate signing process for HttpRequest");
453 goto on_error;
454 }
455
456 return;
457
458 on_error:
459
460 s_cleanup_callback_data(callback_data, env);
461 }
462
463 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSignChunk(JNIEnv * env,jclass jni_class,jobject java_chunk_body_stream,jbyteArray java_previous_signature,jobject java_signing_config,jobject java_signing_result_future)464 void JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSignChunk(
465 JNIEnv *env,
466 jclass jni_class,
467 jobject java_chunk_body_stream,
468 jbyteArray java_previous_signature,
469 jobject java_signing_config,
470 jobject java_signing_result_future) {
471
472 (void)jni_class;
473 aws_cache_jni_ids(env);
474
475 struct aws_allocator *allocator = aws_jni_get_allocator();
476 struct s_aws_sign_request_callback_data *callback_data =
477 aws_mem_calloc(allocator, 1, sizeof(struct s_aws_sign_request_callback_data));
478 if (callback_data == NULL) {
479 aws_jni_throw_runtime_exception(env, "Failed to allocate chunk signing callback data");
480 return;
481 }
482
483 jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
484 AWS_FATAL_ASSERT(jvmresult == 0);
485
486 callback_data->java_signing_result_future = (*env)->NewGlobalRef(env, java_signing_result_future);
487 AWS_FATAL_ASSERT(callback_data->java_signing_result_future != NULL);
488
489 if (java_chunk_body_stream != NULL) {
490 callback_data->java_original_chunk_body = (*env)->NewGlobalRef(env, java_chunk_body_stream);
491 AWS_FATAL_ASSERT(callback_data->java_original_chunk_body != NULL);
492
493 callback_data->chunk_body_stream = aws_input_stream_new_from_java_http_request_body_stream(
494 aws_jni_get_allocator(), env, java_chunk_body_stream);
495 if (callback_data->chunk_body_stream == NULL) {
496 aws_jni_throw_runtime_exception(env, "Error building chunk body stream");
497 goto on_error;
498 }
499 }
500
501 /* Build a native aws_signing_config_aws object */
502 struct aws_signing_config_aws signing_config;
503 AWS_ZERO_STRUCT(signing_config);
504 if (aws_build_signing_config(env, java_signing_config, &callback_data->signing_config_data, &signing_config)) {
505 aws_jni_throw_runtime_exception(env, "Failed to create signing configuration");
506 goto on_error;
507 }
508
509 callback_data->java_previous_signature = (*env)->NewGlobalRef(env, java_previous_signature);
510 callback_data->previous_signature = aws_jni_byte_cursor_from_jbyteArray_acquire(env, java_previous_signature);
511
512 callback_data->original_message_signable =
513 aws_signable_new_chunk(allocator, callback_data->chunk_body_stream, callback_data->previous_signature);
514 if (callback_data->original_message_signable == NULL) {
515 aws_jni_throw_runtime_exception(env, "Failed to create signable from chunk data");
516 goto on_error;
517 }
518
519 /* Sign the native request */
520 if (aws_sign_request_aws(
521 allocator,
522 callback_data->original_message_signable,
523 (struct aws_signing_config_base *)&signing_config,
524 s_aws_chunk_signing_complete,
525 callback_data)) {
526 aws_jni_throw_runtime_exception(env, "Failed to initiate signing process for Chunk");
527 goto on_error;
528 }
529
530 return;
531
532 on_error:
533
534 s_cleanup_callback_data(callback_data, env);
535 }
536
537 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSignTrailingHeaders(JNIEnv * env,jclass jni_class,jbyteArray marshalled_headers,jbyteArray java_previous_signature,jobject java_signing_config,jobject java_signing_result_future)538 void JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigner_awsSignerSignTrailingHeaders(
539 JNIEnv *env,
540 jclass jni_class,
541 jbyteArray marshalled_headers,
542 jbyteArray java_previous_signature,
543 jobject java_signing_config,
544 jobject java_signing_result_future) {
545
546 (void)jni_class;
547 aws_cache_jni_ids(env);
548
549 struct aws_allocator *allocator = aws_jni_get_allocator();
550 struct s_aws_sign_request_callback_data *callback_data =
551 aws_mem_calloc(allocator, 1, sizeof(struct s_aws_sign_request_callback_data));
552 /* we no longer worry about allocation failures */
553
554 jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
555 AWS_FATAL_ASSERT(jvmresult == 0);
556
557 callback_data->java_signing_result_future = (*env)->NewGlobalRef(env, java_signing_result_future);
558 AWS_FATAL_ASSERT(callback_data->java_signing_result_future != NULL);
559
560 callback_data->trailing_headers = aws_http_headers_new_from_java_http_headers(env, marshalled_headers);
561 if (callback_data->trailing_headers == NULL) {
562 goto on_error;
563 }
564
565 /* Build a native aws_signing_config_aws object */
566 struct aws_signing_config_aws signing_config;
567 AWS_ZERO_STRUCT(signing_config);
568
569 if (aws_build_signing_config(env, java_signing_config, &callback_data->signing_config_data, &signing_config)) {
570 aws_jni_throw_runtime_exception(env, "Failed to create signing configuration");
571 goto on_error;
572 }
573
574 callback_data->java_previous_signature = (*env)->NewGlobalRef(env, java_previous_signature);
575 callback_data->previous_signature = aws_jni_byte_cursor_from_jbyteArray_acquire(env, java_previous_signature);
576
577 callback_data->original_message_signable = aws_signable_new_trailing_headers(
578 allocator, callback_data->trailing_headers, callback_data->previous_signature);
579 if (callback_data->original_message_signable == NULL) {
580 aws_jni_throw_runtime_exception(env, "Failed to create signable from trailing headers data");
581 goto on_error;
582 }
583
584 /* Sign the native request */
585 if (aws_sign_request_aws(
586 allocator,
587 callback_data->original_message_signable,
588 (struct aws_signing_config_base *)&signing_config,
589 s_aws_trailing_headers_signing_complete,
590 callback_data)) {
591 aws_jni_throw_runtime_exception(env, "Failed to initiate signing process for trailing headers");
592 goto on_error;
593 }
594
595 return;
596
597 on_error:
598
599 s_cleanup_callback_data(callback_data, env);
600 }
601
602 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_signing_AwsSigningUtils_awsSigningUtilsVerifyEcdsaSignature(JNIEnv * env,jclass jni_class,jobject java_http_request,jbyteArray java_marshalled_request,jstring java_expected_canonical_request,jobject java_signing_config,jbyteArray java_signature,jstring java_verifier_pub_x,jstring java_verifier_pub_y)603 bool JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigningUtils_awsSigningUtilsVerifyEcdsaSignature(
604 JNIEnv *env,
605 jclass jni_class,
606 jobject java_http_request,
607 jbyteArray java_marshalled_request,
608 jstring java_expected_canonical_request,
609 jobject java_signing_config,
610 jbyteArray java_signature,
611 jstring java_verifier_pub_x,
612 jstring java_verifier_pub_y) {
613
614 (void)jni_class;
615 aws_cache_jni_ids(env);
616
617 bool success = false;
618
619 struct aws_string *expected_canonical_request = NULL;
620 struct aws_byte_cursor signature_cursor;
621 AWS_ZERO_STRUCT(signature_cursor);
622 struct aws_string *pub_x = NULL;
623 struct aws_string *pub_y = NULL;
624
625 struct aws_allocator *allocator = aws_jni_get_allocator();
626 struct s_aws_sign_request_callback_data *callback_data =
627 aws_mem_calloc(allocator, 1, sizeof(struct s_aws_sign_request_callback_data));
628 if (callback_data == NULL) {
629 goto done;
630 }
631
632 if (java_signature == NULL) {
633 goto done;
634 }
635
636 signature_cursor = aws_jni_byte_cursor_from_jbyteArray_acquire(env, java_signature);
637 if (signature_cursor.len == 0) {
638 goto done;
639 }
640
641 jint jvmresult = (*env)->GetJavaVM(env, &callback_data->jvm);
642 AWS_FATAL_ASSERT(jvmresult == 0);
643
644 /* Build a native aws_signing_config_aws object */
645 struct aws_signing_config_aws signing_config;
646 AWS_ZERO_STRUCT(signing_config);
647
648 if (aws_build_signing_config(env, java_signing_config, &callback_data->signing_config_data, &signing_config)) {
649 goto done;
650 }
651
652 jobject java_http_request_body_stream =
653 (*env)->GetObjectField(env, java_http_request, http_request_properties.body_stream_field_id);
654
655 callback_data->native_request =
656 aws_http_request_new_from_java_http_request(env, java_marshalled_request, java_http_request_body_stream);
657 if (callback_data->native_request == NULL) {
658 goto done;
659 }
660
661 callback_data->original_message_signable = aws_signable_new_http_request(allocator, callback_data->native_request);
662 if (callback_data->original_message_signable == NULL) {
663 goto done;
664 }
665
666 expected_canonical_request = aws_jni_new_string_from_jstring(env, java_expected_canonical_request);
667 pub_x = aws_jni_new_string_from_jstring(env, java_verifier_pub_x);
668 pub_y = aws_jni_new_string_from_jstring(env, java_verifier_pub_y);
669
670 if (aws_verify_sigv4a_signing(
671 allocator,
672 callback_data->original_message_signable,
673 (struct aws_signing_config_base *)&signing_config,
674 aws_byte_cursor_from_string(expected_canonical_request),
675 signature_cursor,
676 aws_byte_cursor_from_string(pub_x),
677 aws_byte_cursor_from_string(pub_y))) {
678 aws_jni_throw_runtime_exception(env, aws_error_str(aws_last_error()));
679 goto done;
680 }
681
682 success = true;
683
684 done:
685
686 s_cleanup_callback_data(callback_data, env);
687
688 aws_string_destroy(expected_canonical_request);
689 if (signature_cursor.len > 0) {
690 aws_jni_byte_cursor_from_jbyteArray_release(env, java_signature, signature_cursor);
691 }
692 aws_string_destroy(pub_x);
693 aws_string_destroy(pub_y);
694
695 return success;
696 }
697
698 JNIEXPORT
Java_software_amazon_awssdk_crt_auth_signing_AwsSigningUtils_awsSigningUtilsVerifyRawSha256EcdsaSignature(JNIEnv * env,jclass jni_class,jbyteArray java_string_to_sign,jbyteArray java_signature,jstring java_verifier_pub_x,jstring java_verifier_pub_y)699 bool JNICALL Java_software_amazon_awssdk_crt_auth_signing_AwsSigningUtils_awsSigningUtilsVerifyRawSha256EcdsaSignature(
700 JNIEnv *env,
701 jclass jni_class,
702 jbyteArray java_string_to_sign,
703 jbyteArray java_signature,
704 jstring java_verifier_pub_x,
705 jstring java_verifier_pub_y) {
706
707 (void)jni_class;
708 aws_cache_jni_ids(env);
709
710 bool success = false;
711 struct aws_allocator *allocator = aws_jni_get_allocator();
712
713 struct aws_byte_cursor string_to_sign_cursor;
714 AWS_ZERO_STRUCT(string_to_sign_cursor);
715 struct aws_byte_cursor signature_cursor;
716 AWS_ZERO_STRUCT(signature_cursor);
717
718 struct aws_ecc_key_pair *ecc_key = NULL;
719 struct aws_string *pub_x = NULL;
720 struct aws_string *pub_y = NULL;
721
722 if (java_string_to_sign == NULL || java_signature == NULL || java_verifier_pub_x == NULL ||
723 java_verifier_pub_y == NULL) {
724 goto done;
725 }
726
727 pub_x = aws_jni_new_string_from_jstring(env, java_verifier_pub_x);
728 pub_y = aws_jni_new_string_from_jstring(env, java_verifier_pub_y);
729 if (pub_x == NULL || pub_y == NULL) {
730 goto done;
731 }
732
733 ecc_key = aws_ecc_key_new_from_hex_coordinates(
734 allocator, AWS_CAL_ECDSA_P256, aws_byte_cursor_from_string(pub_x), aws_byte_cursor_from_string(pub_y));
735 if (ecc_key == NULL) {
736 goto done;
737 }
738
739 string_to_sign_cursor = aws_jni_byte_cursor_from_jbyteArray_acquire(env, java_string_to_sign);
740 signature_cursor = aws_jni_byte_cursor_from_jbyteArray_acquire(env, java_signature);
741
742 if (aws_validate_v4a_authorization_value(allocator, ecc_key, string_to_sign_cursor, signature_cursor)) {
743 goto done;
744 }
745
746 success = true;
747
748 done:
749
750 if (string_to_sign_cursor.len > 0) {
751 aws_jni_byte_cursor_from_jbyteArray_release(env, java_string_to_sign, string_to_sign_cursor);
752 }
753
754 if (signature_cursor.len > 0) {
755 aws_jni_byte_cursor_from_jbyteArray_release(env, java_signature, signature_cursor);
756 }
757
758 aws_string_destroy(pub_x);
759 aws_string_destroy(pub_y);
760
761 aws_ecc_key_pair_release(ecc_key);
762
763 return success;
764 }
765
766 #if UINTPTR_MAX == 0xffffffff
767 # if defined(_MSC_VER)
768 # pragma warning(pop)
769 # else
770 # pragma GCC diagnostic pop
771 # endif
772 #endif
773