aws_signing.c 92 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/auth/private/aws_signing.h>
  6. #include <aws/auth/credentials.h>
  7. #include <aws/auth/private/key_derivation.h>
  8. #include <aws/auth/signable.h>
  9. #include <aws/auth/signing.h>
  10. #include <aws/cal/ecc.h>
  11. #include <aws/cal/hash.h>
  12. #include <aws/cal/hmac.h>
  13. #include <aws/common/date_time.h>
  14. #include <aws/common/encoding.h>
  15. #include <aws/common/string.h>
  16. #include <aws/io/stream.h>
  17. #include <aws/io/uri.h>
  18. #include <ctype.h>
  19. #include <inttypes.h>
  20. #if defined(_MSC_VER)
  21. # pragma warning(disable : 4204)
  22. #endif /* _MSC_VER */
  23. /*
  24. * A bunch of initial size values for various buffers used throughout the signing process
  25. *
  26. * We want them to be sufficient-but-not-wasting-significant-amounts-of-memory for "most"
  27. * requests. The body read buffer is an exception since it will just be holding windows rather than
  28. * the entire thing.
  29. */
  30. #define BODY_READ_BUFFER_SIZE 4096
  31. #define CANONICAL_REQUEST_STARTING_SIZE 1024
  32. #define STRING_TO_SIGN_STARTING_SIZE 256
  33. #define SIGNED_HEADERS_STARTING_SIZE 256
  34. #define CANONICAL_HEADER_BLOCK_STARTING_SIZE 1024
  35. #define AUTHORIZATION_VALUE_STARTING_SIZE 512
  36. #define PAYLOAD_HASH_STARTING_SIZE (AWS_SHA256_LEN * 2)
  37. #define CREDENTIAL_SCOPE_STARTING_SIZE 128
  38. #define ACCESS_CREDENTIAL_SCOPE_STARTING_SIZE 149
  39. #define SCRATCH_BUF_STARTING_SIZE 256
  40. #define MAX_AUTHORIZATION_HEADER_COUNT 4
  41. #define MAX_AUTHORIZATION_QUERY_PARAM_COUNT 6
  42. #define DEFAULT_PATH_COMPONENT_COUNT 10
  43. #define CANONICAL_REQUEST_SPLIT_OVER_ESTIMATE 20
  44. #define HEX_ENCODED_SIGNATURE_OVER_ESTIMATE 256
  45. #define MAX_ECDSA_P256_SIGNATURE_AS_BINARY_LENGTH 72
  46. #define MAX_ECDSA_P256_SIGNATURE_AS_HEX_LENGTH (MAX_ECDSA_P256_SIGNATURE_AS_BINARY_LENGTH * 2)
  47. #define AWS_SIGV4A_SIGNATURE_PADDING_BYTE ('*')
  48. AWS_STRING_FROM_LITERAL(g_aws_signing_content_header_name, "x-amz-content-sha256");
  49. AWS_STRING_FROM_LITERAL(g_aws_signing_authorization_header_name, "Authorization");
  50. AWS_STRING_FROM_LITERAL(g_aws_signing_authorization_query_param_name, "X-Amz-Signature");
  51. AWS_STRING_FROM_LITERAL(g_aws_signing_algorithm_query_param_name, "X-Amz-Algorithm");
  52. AWS_STRING_FROM_LITERAL(g_aws_signing_credential_query_param_name, "X-Amz-Credential");
  53. AWS_STRING_FROM_LITERAL(g_aws_signing_date_name, "X-Amz-Date");
  54. AWS_STRING_FROM_LITERAL(g_aws_signing_signed_headers_query_param_name, "X-Amz-SignedHeaders");
  55. AWS_STRING_FROM_LITERAL(g_aws_signing_security_token_name, "X-Amz-Security-Token");
  56. AWS_STRING_FROM_LITERAL(g_aws_signing_expires_query_param_name, "X-Amz-Expires");
  57. AWS_STRING_FROM_LITERAL(g_aws_signing_region_set_name, "X-Amz-Region-Set");
  58. AWS_STATIC_STRING_FROM_LITERAL(s_signature_type_sigv4_http_request, "AWS4-HMAC-SHA256");
  59. AWS_STATIC_STRING_FROM_LITERAL(s_signature_type_sigv4_s3_chunked_payload, "AWS4-HMAC-SHA256-PAYLOAD");
  60. AWS_STATIC_STRING_FROM_LITERAL(s_signature_type_sigv4a_s3_chunked_payload, "AWS4-ECDSA-P256-SHA256-PAYLOAD");
  61. AWS_STATIC_STRING_FROM_LITERAL(s_signature_type_sigv4_s3_chunked_trailer_payload, "AWS4-HMAC-SHA256-TRAILER");
  62. AWS_STATIC_STRING_FROM_LITERAL(s_signature_type_sigv4a_s3_chunked_trailer_payload, "AWS4-ECDSA-P256-SHA256-TRAILER");
  63. /* aws-related query param and header tables */
  64. static struct aws_hash_table s_forbidden_headers;
  65. static struct aws_hash_table s_forbidden_params;
  66. static struct aws_hash_table s_skipped_headers;
  67. static struct aws_byte_cursor s_amzn_trace_id_header_name;
  68. static struct aws_byte_cursor s_user_agent_header_name;
  69. static struct aws_byte_cursor s_connection_header_name;
  70. static struct aws_byte_cursor s_sec_websocket_key_header_name;
  71. static struct aws_byte_cursor s_sec_websocket_protocol_header_name;
  72. static struct aws_byte_cursor s_sec_websocket_version_header_name;
  73. static struct aws_byte_cursor s_upgrade_header_name;
  74. static struct aws_byte_cursor s_amz_content_sha256_header_name;
  75. static struct aws_byte_cursor s_amz_date_header_name;
  76. static struct aws_byte_cursor s_authorization_header_name;
  77. static struct aws_byte_cursor s_region_set_header_name;
  78. static struct aws_byte_cursor s_amz_security_token_header_name;
  79. static struct aws_byte_cursor s_amz_signature_param_name;
  80. static struct aws_byte_cursor s_amz_date_param_name;
  81. static struct aws_byte_cursor s_amz_credential_param_name;
  82. static struct aws_byte_cursor s_amz_algorithm_param_name;
  83. static struct aws_byte_cursor s_amz_signed_headers_param_name;
  84. static struct aws_byte_cursor s_amz_security_token_param_name;
  85. static struct aws_byte_cursor s_amz_expires_param_name;
  86. static struct aws_byte_cursor s_amz_region_set_param_name;
  87. /*
  88. * Build a set of library-static tables for quick lookup.
  89. *
  90. * Construction errors are considered fatal.
  91. */
  92. int aws_signing_init_signing_tables(struct aws_allocator *allocator) {
  93. if (aws_hash_table_init(
  94. &s_skipped_headers,
  95. allocator,
  96. 10,
  97. aws_hash_byte_cursor_ptr_ignore_case,
  98. (aws_hash_callback_eq_fn *)aws_byte_cursor_eq_ignore_case,
  99. NULL,
  100. NULL)) {
  101. return AWS_OP_ERR;
  102. }
  103. s_amzn_trace_id_header_name = aws_byte_cursor_from_c_str("x-amzn-trace-id");
  104. if (aws_hash_table_put(&s_skipped_headers, &s_amzn_trace_id_header_name, NULL, NULL)) {
  105. return AWS_OP_ERR;
  106. }
  107. s_user_agent_header_name = aws_byte_cursor_from_c_str("User-Agent");
  108. if (aws_hash_table_put(&s_skipped_headers, &s_user_agent_header_name, NULL, NULL)) {
  109. return AWS_OP_ERR;
  110. }
  111. s_connection_header_name = aws_byte_cursor_from_c_str("connection");
  112. if (aws_hash_table_put(&s_skipped_headers, &s_connection_header_name, NULL, NULL)) {
  113. return AWS_OP_ERR;
  114. }
  115. s_connection_header_name = aws_byte_cursor_from_c_str("expect");
  116. if (aws_hash_table_put(&s_skipped_headers, &s_connection_header_name, NULL, NULL)) {
  117. return AWS_OP_ERR;
  118. }
  119. s_sec_websocket_key_header_name = aws_byte_cursor_from_c_str("sec-websocket-key");
  120. if (aws_hash_table_put(&s_skipped_headers, &s_sec_websocket_key_header_name, NULL, NULL)) {
  121. return AWS_OP_ERR;
  122. }
  123. s_sec_websocket_protocol_header_name = aws_byte_cursor_from_c_str("sec-websocket-protocol");
  124. if (aws_hash_table_put(&s_skipped_headers, &s_sec_websocket_protocol_header_name, NULL, NULL)) {
  125. return AWS_OP_ERR;
  126. }
  127. s_sec_websocket_version_header_name = aws_byte_cursor_from_c_str("sec-websocket-version");
  128. if (aws_hash_table_put(&s_skipped_headers, &s_sec_websocket_version_header_name, NULL, NULL)) {
  129. return AWS_OP_ERR;
  130. }
  131. s_upgrade_header_name = aws_byte_cursor_from_c_str("upgrade");
  132. if (aws_hash_table_put(&s_skipped_headers, &s_upgrade_header_name, NULL, NULL)) {
  133. return AWS_OP_ERR;
  134. }
  135. if (aws_hash_table_init(
  136. &s_forbidden_headers,
  137. allocator,
  138. 10,
  139. aws_hash_byte_cursor_ptr_ignore_case,
  140. (aws_hash_callback_eq_fn *)aws_byte_cursor_eq_ignore_case,
  141. NULL,
  142. NULL)) {
  143. return AWS_OP_ERR;
  144. }
  145. s_amz_content_sha256_header_name = aws_byte_cursor_from_string(g_aws_signing_content_header_name);
  146. if (aws_hash_table_put(&s_forbidden_headers, &s_amz_content_sha256_header_name, NULL, NULL)) {
  147. return AWS_OP_ERR;
  148. }
  149. s_amz_date_header_name = aws_byte_cursor_from_string(g_aws_signing_date_name);
  150. if (aws_hash_table_put(&s_forbidden_headers, &s_amz_date_header_name, NULL, NULL)) {
  151. return AWS_OP_ERR;
  152. }
  153. s_authorization_header_name = aws_byte_cursor_from_string(g_aws_signing_authorization_header_name);
  154. if (aws_hash_table_put(&s_forbidden_headers, &s_authorization_header_name, NULL, NULL)) {
  155. return AWS_OP_ERR;
  156. }
  157. s_region_set_header_name = aws_byte_cursor_from_string(g_aws_signing_region_set_name);
  158. if (aws_hash_table_put(&s_forbidden_headers, &s_region_set_header_name, NULL, NULL)) {
  159. return AWS_OP_ERR;
  160. }
  161. s_amz_security_token_header_name = aws_byte_cursor_from_string(g_aws_signing_security_token_name);
  162. if (aws_hash_table_put(&s_forbidden_headers, &s_amz_security_token_header_name, NULL, NULL)) {
  163. return AWS_OP_ERR;
  164. }
  165. if (aws_hash_table_init(
  166. &s_forbidden_params,
  167. allocator,
  168. 10,
  169. aws_hash_byte_cursor_ptr_ignore_case,
  170. (aws_hash_callback_eq_fn *)aws_byte_cursor_eq_ignore_case,
  171. NULL,
  172. NULL)) {
  173. return AWS_OP_ERR;
  174. }
  175. s_amz_signature_param_name = aws_byte_cursor_from_string(g_aws_signing_authorization_query_param_name);
  176. if (aws_hash_table_put(&s_forbidden_params, &s_amz_signature_param_name, NULL, NULL)) {
  177. return AWS_OP_ERR;
  178. }
  179. s_amz_date_param_name = aws_byte_cursor_from_string(g_aws_signing_date_name);
  180. if (aws_hash_table_put(&s_forbidden_params, &s_amz_date_param_name, NULL, NULL)) {
  181. return AWS_OP_ERR;
  182. }
  183. s_amz_credential_param_name = aws_byte_cursor_from_string(g_aws_signing_credential_query_param_name);
  184. if (aws_hash_table_put(&s_forbidden_params, &s_amz_credential_param_name, NULL, NULL)) {
  185. return AWS_OP_ERR;
  186. }
  187. s_amz_algorithm_param_name = aws_byte_cursor_from_string(g_aws_signing_algorithm_query_param_name);
  188. if (aws_hash_table_put(&s_forbidden_params, &s_amz_algorithm_param_name, NULL, NULL)) {
  189. return AWS_OP_ERR;
  190. }
  191. s_amz_signed_headers_param_name = aws_byte_cursor_from_string(g_aws_signing_signed_headers_query_param_name);
  192. if (aws_hash_table_put(&s_forbidden_params, &s_amz_signed_headers_param_name, NULL, NULL)) {
  193. return AWS_OP_ERR;
  194. }
  195. s_amz_security_token_param_name = aws_byte_cursor_from_string(g_aws_signing_security_token_name);
  196. if (aws_hash_table_put(&s_forbidden_params, &s_amz_security_token_param_name, NULL, NULL)) {
  197. return AWS_OP_ERR;
  198. }
  199. s_amz_expires_param_name = aws_byte_cursor_from_string(g_aws_signing_expires_query_param_name);
  200. if (aws_hash_table_put(&s_forbidden_params, &s_amz_expires_param_name, NULL, NULL)) {
  201. return AWS_OP_ERR;
  202. }
  203. s_amz_region_set_param_name = aws_byte_cursor_from_string(g_aws_signing_region_set_name);
  204. if (aws_hash_table_put(&s_forbidden_params, &s_amz_region_set_param_name, NULL, NULL)) {
  205. return AWS_OP_ERR;
  206. }
  207. return AWS_OP_SUCCESS;
  208. }
  209. void aws_signing_clean_up_signing_tables(void) {
  210. aws_hash_table_clean_up(&s_skipped_headers);
  211. aws_hash_table_clean_up(&s_forbidden_headers);
  212. aws_hash_table_clean_up(&s_forbidden_params);
  213. }
  214. static bool s_is_header_based_signature_value(enum aws_signature_type signature_type) {
  215. switch (signature_type) {
  216. case AWS_ST_HTTP_REQUEST_HEADERS:
  217. case AWS_ST_CANONICAL_REQUEST_HEADERS:
  218. return true;
  219. default:
  220. return false;
  221. }
  222. }
  223. static bool s_is_query_param_based_signature_value(enum aws_signature_type signature_type) {
  224. switch (signature_type) {
  225. case AWS_ST_HTTP_REQUEST_QUERY_PARAMS:
  226. case AWS_ST_CANONICAL_REQUEST_QUERY_PARAMS:
  227. return true;
  228. default:
  229. return false;
  230. }
  231. }
  232. static int s_get_signature_type_cursor(struct aws_signing_state_aws *state, struct aws_byte_cursor *cursor) {
  233. switch (state->config.signature_type) {
  234. case AWS_ST_HTTP_REQUEST_HEADERS:
  235. case AWS_ST_HTTP_REQUEST_QUERY_PARAMS:
  236. case AWS_ST_CANONICAL_REQUEST_HEADERS:
  237. case AWS_ST_CANONICAL_REQUEST_QUERY_PARAMS:
  238. if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4) {
  239. *cursor = aws_byte_cursor_from_string(s_signature_type_sigv4_http_request);
  240. } else {
  241. *cursor = aws_byte_cursor_from_string(g_signature_type_sigv4a_http_request);
  242. }
  243. break;
  244. case AWS_ST_HTTP_REQUEST_CHUNK:
  245. case AWS_ST_HTTP_REQUEST_EVENT:
  246. if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4) {
  247. *cursor = aws_byte_cursor_from_string(s_signature_type_sigv4_s3_chunked_payload);
  248. } else {
  249. *cursor = aws_byte_cursor_from_string(s_signature_type_sigv4a_s3_chunked_payload);
  250. }
  251. break;
  252. case AWS_ST_HTTP_REQUEST_TRAILING_HEADERS:
  253. if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4) {
  254. *cursor = aws_byte_cursor_from_string(s_signature_type_sigv4_s3_chunked_trailer_payload);
  255. } else {
  256. *cursor = aws_byte_cursor_from_string(s_signature_type_sigv4a_s3_chunked_trailer_payload);
  257. }
  258. break;
  259. default:
  260. return aws_raise_error(AWS_AUTH_SIGNING_UNSUPPORTED_SIGNATURE_TYPE);
  261. }
  262. return AWS_OP_SUCCESS;
  263. }
  264. static int s_append_sts_signature_type(struct aws_signing_state_aws *state, struct aws_byte_buf *dest) {
  265. struct aws_byte_cursor algorithm_cursor;
  266. if (s_get_signature_type_cursor(state, &algorithm_cursor)) {
  267. return AWS_OP_ERR;
  268. }
  269. return aws_byte_buf_append_dynamic(dest, &algorithm_cursor);
  270. }
  271. /*
  272. * signing state management
  273. */
  274. struct aws_signing_state_aws *aws_signing_state_new(
  275. struct aws_allocator *allocator,
  276. const struct aws_signing_config_aws *config,
  277. const struct aws_signable *signable,
  278. aws_signing_complete_fn *on_complete,
  279. void *userdata) {
  280. if (aws_validate_aws_signing_config_aws(config)) {
  281. return NULL;
  282. }
  283. struct aws_signing_state_aws *state = aws_mem_calloc(allocator, 1, sizeof(struct aws_signing_state_aws));
  284. if (!state) {
  285. return NULL;
  286. }
  287. state->allocator = allocator;
  288. /* Make our own copy of the signing config */
  289. state->config = *config;
  290. if (state->config.credentials_provider != NULL) {
  291. aws_credentials_provider_acquire(state->config.credentials_provider);
  292. }
  293. if (state->config.credentials != NULL) {
  294. aws_credentials_acquire(state->config.credentials);
  295. }
  296. if (aws_byte_buf_init_cache_and_update_cursors(
  297. &state->config_string_buffer,
  298. allocator,
  299. &state->config.region,
  300. &state->config.service,
  301. &state->config.signed_body_value,
  302. NULL /*end*/)) {
  303. goto on_error;
  304. }
  305. state->signable = signable;
  306. state->on_complete = on_complete;
  307. state->userdata = userdata;
  308. if (aws_signing_result_init(&state->result, allocator)) {
  309. goto on_error;
  310. }
  311. if (aws_byte_buf_init(&state->canonical_request, allocator, CANONICAL_REQUEST_STARTING_SIZE) ||
  312. aws_byte_buf_init(&state->string_to_sign, allocator, STRING_TO_SIGN_STARTING_SIZE) ||
  313. aws_byte_buf_init(&state->signed_headers, allocator, SIGNED_HEADERS_STARTING_SIZE) ||
  314. aws_byte_buf_init(&state->canonical_header_block, allocator, CANONICAL_HEADER_BLOCK_STARTING_SIZE) ||
  315. aws_byte_buf_init(&state->payload_hash, allocator, PAYLOAD_HASH_STARTING_SIZE) ||
  316. aws_byte_buf_init(&state->credential_scope, allocator, CREDENTIAL_SCOPE_STARTING_SIZE) ||
  317. aws_byte_buf_init(&state->access_credential_scope, allocator, ACCESS_CREDENTIAL_SCOPE_STARTING_SIZE) ||
  318. aws_byte_buf_init(&state->date, allocator, AWS_DATE_TIME_STR_MAX_LEN) ||
  319. aws_byte_buf_init(&state->signature, allocator, PAYLOAD_HASH_STARTING_SIZE) ||
  320. aws_byte_buf_init(&state->string_to_sign_payload, allocator, PAYLOAD_HASH_STARTING_SIZE) ||
  321. aws_byte_buf_init(&state->scratch_buf, allocator, SCRATCH_BUF_STARTING_SIZE)) {
  322. goto on_error;
  323. }
  324. snprintf(
  325. state->expiration_array, AWS_ARRAY_SIZE(state->expiration_array), "%" PRIu64 "", config->expiration_in_seconds);
  326. return state;
  327. on_error:
  328. aws_signing_state_destroy(state);
  329. return NULL;
  330. }
  331. void aws_signing_state_destroy(struct aws_signing_state_aws *state) {
  332. aws_signing_result_clean_up(&state->result);
  333. aws_credentials_provider_release(state->config.credentials_provider);
  334. aws_credentials_release(state->config.credentials);
  335. aws_byte_buf_clean_up(&state->config_string_buffer);
  336. aws_byte_buf_clean_up(&state->canonical_request);
  337. aws_byte_buf_clean_up(&state->string_to_sign);
  338. aws_byte_buf_clean_up(&state->signed_headers);
  339. aws_byte_buf_clean_up(&state->canonical_header_block);
  340. aws_byte_buf_clean_up(&state->payload_hash);
  341. aws_byte_buf_clean_up(&state->credential_scope);
  342. aws_byte_buf_clean_up(&state->access_credential_scope);
  343. aws_byte_buf_clean_up(&state->date);
  344. aws_byte_buf_clean_up(&state->signature);
  345. aws_byte_buf_clean_up(&state->string_to_sign_payload);
  346. aws_byte_buf_clean_up(&state->scratch_buf);
  347. aws_mem_release(state->allocator, state);
  348. }
  349. /*
  350. * canonical request utility functions:
  351. *
  352. * various appends, conversion/encoding, etc...
  353. *
  354. */
  355. static int s_append_canonical_method(struct aws_signing_state_aws *state) {
  356. const struct aws_signable *signable = state->signable;
  357. struct aws_byte_buf *buffer = &state->canonical_request;
  358. struct aws_byte_cursor method_cursor;
  359. aws_signable_get_property(signable, g_aws_http_method_property_name, &method_cursor);
  360. if (aws_byte_buf_append_dynamic(buffer, &method_cursor)) {
  361. return AWS_OP_ERR;
  362. }
  363. if (aws_byte_buf_append_byte_dynamic(buffer, '\n')) {
  364. return AWS_OP_ERR;
  365. }
  366. return AWS_OP_SUCCESS;
  367. }
  368. static int s_append_with_lookup(
  369. struct aws_byte_buf *dst,
  370. const struct aws_byte_cursor *src,
  371. const uint8_t *lookup_table) {
  372. if (aws_byte_buf_reserve_relative(dst, src->len)) {
  373. return AWS_OP_ERR;
  374. }
  375. if (aws_byte_buf_append_with_lookup(dst, src, lookup_table)) {
  376. return AWS_OP_ERR;
  377. }
  378. return AWS_OP_SUCCESS;
  379. }
  380. /*
  381. * A function that builds a normalized path (removes redundant '/' characters, '.' components, and properly pops off
  382. * components in response '..' components)
  383. *
  384. * We use a simple algorithm to do this:
  385. *
  386. * First split the path into components
  387. * Then, using a secondary stack of components, build the final path by pushing and popping (on '..') components
  388. * on the stack. The final path is then the concatenation of the secondary stack.
  389. */
  390. static int s_append_normalized_path(
  391. const struct aws_byte_cursor *raw_path,
  392. struct aws_allocator *allocator,
  393. struct aws_byte_buf *dest) {
  394. struct aws_array_list raw_split;
  395. AWS_ZERO_STRUCT(raw_split);
  396. struct aws_array_list normalized_split;
  397. AWS_ZERO_STRUCT(normalized_split);
  398. int result = AWS_OP_ERR;
  399. if (aws_array_list_init_dynamic(
  400. &raw_split, allocator, DEFAULT_PATH_COMPONENT_COUNT, sizeof(struct aws_byte_cursor))) {
  401. goto cleanup;
  402. }
  403. if (aws_byte_cursor_split_on_char(raw_path, '/', &raw_split)) {
  404. goto cleanup;
  405. }
  406. const size_t raw_split_count = aws_array_list_length(&raw_split);
  407. if (aws_array_list_init_dynamic(&normalized_split, allocator, raw_split_count, sizeof(struct aws_byte_cursor))) {
  408. goto cleanup;
  409. }
  410. /*
  411. * Iterate the raw split to build a list of path components that make up the
  412. * normalized path
  413. */
  414. for (size_t i = 0; i < raw_split_count; ++i) {
  415. struct aws_byte_cursor path_component;
  416. AWS_ZERO_STRUCT(path_component);
  417. if (aws_array_list_get_at(&raw_split, &path_component, i)) {
  418. goto cleanup;
  419. }
  420. if (path_component.len == 0 || (path_component.len == 1 && *path_component.ptr == '.')) {
  421. /* '.' and '' contribute nothing to a normalized path */
  422. continue;
  423. }
  424. if (path_component.len == 2 && *path_component.ptr == '.' && *(path_component.ptr + 1) == '.') {
  425. /* '..' causes us to remove the last valid path component */
  426. aws_array_list_pop_back(&normalized_split);
  427. } else {
  428. aws_array_list_push_back(&normalized_split, &path_component);
  429. }
  430. }
  431. /*
  432. * Special case preserve whether or not the path ended with a '/'
  433. */
  434. bool ends_with_slash = raw_path->len > 0 && raw_path->ptr[raw_path->len - 1] == '/';
  435. /*
  436. * Paths always start with a single '/'
  437. */
  438. if (aws_byte_buf_append_byte_dynamic(dest, '/')) {
  439. goto cleanup;
  440. }
  441. /*
  442. * build the final normalized path from the normalized split by joining
  443. * the components together with '/'
  444. */
  445. const size_t normalized_split_count = aws_array_list_length(&normalized_split);
  446. for (size_t i = 0; i < normalized_split_count; ++i) {
  447. struct aws_byte_cursor normalized_path_component;
  448. AWS_ZERO_STRUCT(normalized_path_component);
  449. if (aws_array_list_get_at(&normalized_split, &normalized_path_component, i)) {
  450. goto cleanup;
  451. }
  452. if (aws_byte_buf_append_dynamic(dest, &normalized_path_component)) {
  453. goto cleanup;
  454. }
  455. if (i + 1 < normalized_split_count || ends_with_slash) {
  456. if (aws_byte_buf_append_byte_dynamic(dest, '/')) {
  457. goto cleanup;
  458. }
  459. }
  460. }
  461. result = AWS_OP_SUCCESS;
  462. cleanup:
  463. aws_array_list_clean_up(&raw_split);
  464. aws_array_list_clean_up(&normalized_split);
  465. return result;
  466. }
  467. static int s_append_canonical_path(const struct aws_uri *uri, struct aws_signing_state_aws *state) {
  468. const struct aws_signing_config_aws *config = &state->config;
  469. struct aws_byte_buf *canonical_request_buffer = &state->canonical_request;
  470. struct aws_allocator *allocator = state->allocator;
  471. int result = AWS_OP_ERR;
  472. /*
  473. * Put this at function global scope so that it gets cleaned up even though it's only used inside
  474. * a single branch. Allows error handling and cleanup to follow the pattern established
  475. * throughout this file.
  476. */
  477. struct aws_byte_buf normalized_path;
  478. AWS_ZERO_STRUCT(normalized_path);
  479. /*
  480. * We assume the request's uri path has already been encoded once (in order to go out on the wire).
  481. * Some services do not decode the path before performing the sig v4 calculation, resulting in the
  482. * service actually performing sigv4 on a double-encoding of the path. In order to match those
  483. * services, we must double encode in our calculation as well.
  484. */
  485. if (config->flags.use_double_uri_encode) {
  486. struct aws_byte_cursor path_cursor;
  487. /*
  488. * We need to transform the the normalized path, so we can't just append it into the canonical
  489. * request. Instead we append it into a temporary buffer and perform the transformation from
  490. * it.
  491. *
  492. * All this does is skip the temporary normalized path in the case where we don't need to
  493. * double encode.
  494. */
  495. if (config->flags.should_normalize_uri_path) {
  496. if (aws_byte_buf_init(&normalized_path, state->allocator, uri->path.len)) {
  497. goto cleanup;
  498. }
  499. if (s_append_normalized_path(&uri->path, allocator, &normalized_path)) {
  500. goto cleanup;
  501. }
  502. path_cursor = aws_byte_cursor_from_buf(&normalized_path);
  503. } else {
  504. path_cursor = uri->path;
  505. }
  506. if (aws_byte_buf_append_encoding_uri_path(canonical_request_buffer, &path_cursor)) {
  507. goto cleanup;
  508. }
  509. } else {
  510. /*
  511. * If we don't need to perform any kind of transformation on the normalized path, just append it directly
  512. * into the canonical request buffer
  513. */
  514. if (config->flags.should_normalize_uri_path) {
  515. if (s_append_normalized_path(&uri->path, allocator, canonical_request_buffer)) {
  516. goto cleanup;
  517. }
  518. } else {
  519. if (aws_byte_buf_append_dynamic(canonical_request_buffer, &uri->path)) {
  520. goto cleanup;
  521. }
  522. }
  523. }
  524. if (aws_byte_buf_append_byte_dynamic(canonical_request_buffer, '\n')) {
  525. goto cleanup;
  526. }
  527. result = AWS_OP_SUCCESS;
  528. cleanup:
  529. aws_byte_buf_clean_up(&normalized_path);
  530. return result;
  531. }
  532. /*
  533. * URI-encoded query params are compared first by key, then by value
  534. */
  535. int s_canonical_query_param_comparator(const void *lhs, const void *rhs) {
  536. const struct aws_uri_param *left_param = lhs;
  537. const struct aws_uri_param *right_param = rhs;
  538. int key_compare = aws_byte_cursor_compare_lexical(&left_param->key, &right_param->key);
  539. if (key_compare != 0) {
  540. return key_compare;
  541. }
  542. return aws_byte_cursor_compare_lexical(&left_param->value, &right_param->value);
  543. }
  544. /*
  545. * We need to sort the headers in a stable fashion, but the default sorting methods available in the c library are not
  546. * guaranteed to be stable. We can make the sort stable by instead sorting a wrapper object that includes the original
  547. * index of the wrapped object and using that index to break lexical ties.
  548. *
  549. * We sort a copy of the header (rather than pointers) so that we can easily inject secondary headers into
  550. * the canonical request.
  551. */
  552. struct stable_header {
  553. struct aws_signable_property_list_pair header;
  554. size_t original_index;
  555. };
  556. int s_canonical_header_comparator(const void *lhs, const void *rhs) {
  557. const struct stable_header *left_header = lhs;
  558. const struct stable_header *right_header = rhs;
  559. int result = aws_byte_cursor_compare_lookup(
  560. &left_header->header.name, &right_header->header.name, aws_lookup_table_to_lower_get());
  561. if (result != 0) {
  562. return result;
  563. }
  564. /* they're the same header, use the original index to keep the sort stable */
  565. if (left_header->original_index < right_header->original_index) {
  566. return -1;
  567. }
  568. /* equality should never happen */
  569. AWS_ASSERT(left_header->original_index > right_header->original_index);
  570. return 1;
  571. }
  572. /**
  573. * Given URI-encoded query param, write it to canonical buffer.
  574. */
  575. static int s_append_canonical_query_param(struct aws_uri_param *encoded_param, struct aws_byte_buf *buffer) {
  576. if (aws_byte_buf_append_dynamic(buffer, &encoded_param->key)) {
  577. return AWS_OP_ERR;
  578. }
  579. if (aws_byte_buf_append_byte_dynamic(buffer, '=')) {
  580. return AWS_OP_ERR;
  581. }
  582. if (aws_byte_buf_append_dynamic(buffer, &encoded_param->value)) {
  583. return AWS_OP_ERR;
  584. }
  585. return AWS_OP_SUCCESS;
  586. }
  587. /**
  588. * Given unencoded authorization query param:
  589. * Add it, URI-encoded to final signing result (to be added to signable later).
  590. */
  591. static int s_add_query_param_to_signing_result(
  592. struct aws_signing_state_aws *state,
  593. const struct aws_uri_param *unencoded_param) {
  594. /* URI-Encode, and add to final signing result */
  595. state->scratch_buf.len = 0;
  596. if (aws_byte_buf_append_encoding_uri_param(&state->scratch_buf, &unencoded_param->key)) {
  597. return AWS_OP_ERR;
  598. }
  599. size_t key_len = state->scratch_buf.len;
  600. if (aws_byte_buf_append_encoding_uri_param(&state->scratch_buf, &unencoded_param->value)) {
  601. return AWS_OP_ERR;
  602. }
  603. struct aws_byte_cursor encoded_val = aws_byte_cursor_from_buf(&state->scratch_buf);
  604. struct aws_byte_cursor encoded_key = aws_byte_cursor_advance(&encoded_val, key_len);
  605. if (aws_signing_result_append_property_list(
  606. &state->result, g_aws_http_query_params_property_list_name, &encoded_key, &encoded_val)) {
  607. return AWS_OP_ERR;
  608. }
  609. return AWS_OP_SUCCESS;
  610. }
  611. /**
  612. * Given unencoded authorization query param:
  613. * 1) Add it to list of all unencoded query params (to be canonicalized later).
  614. * 2) Add it, URI-encoded to final signing result (to be added to signable later).
  615. */
  616. static int s_add_authorization_query_param(
  617. struct aws_signing_state_aws *state,
  618. struct aws_array_list *unencoded_auth_params,
  619. const struct aws_uri_param *unencoded_auth_param) {
  620. /* Add to unencoded list */
  621. if (aws_array_list_push_back(unencoded_auth_params, unencoded_auth_param)) {
  622. return AWS_OP_ERR;
  623. }
  624. return s_add_query_param_to_signing_result(state, unencoded_auth_param);
  625. }
  626. /*
  627. * Checks the header against both an internal skip list as well as an optional user-supplied filter
  628. * function. Only sign the header if both functions allow it.
  629. */
  630. static bool s_should_sign_header(struct aws_signing_state_aws *state, struct aws_byte_cursor *name) {
  631. if (state->config.should_sign_header) {
  632. if (!state->config.should_sign_header(name, state->config.should_sign_header_ud)) {
  633. return false;
  634. }
  635. }
  636. struct aws_hash_element *element = NULL;
  637. if (aws_hash_table_find(&s_skipped_headers, name, &element) == AWS_OP_ERR || element != NULL) {
  638. return false;
  639. }
  640. return true;
  641. }
  642. /*
  643. * If the auth type was query param then this function adds all the required query params and values with the
  644. * exception of X-Amz-Signature (because we're still computing its value) Parameters are added to both the
  645. * canonical request and the final signing result.
  646. */
  647. static int s_add_authorization_query_params(
  648. struct aws_signing_state_aws *state,
  649. struct aws_array_list *unencoded_query_params) {
  650. if (state->config.signature_type != AWS_ST_HTTP_REQUEST_QUERY_PARAMS) {
  651. return AWS_OP_SUCCESS;
  652. }
  653. int result = AWS_OP_ERR;
  654. /* X-Amz-Algorithm */
  655. struct aws_uri_param algorithm_param = {
  656. .key = aws_byte_cursor_from_string(g_aws_signing_algorithm_query_param_name),
  657. };
  658. if (s_get_signature_type_cursor(state, &algorithm_param.value)) {
  659. goto done;
  660. }
  661. if (s_add_authorization_query_param(state, unencoded_query_params, &algorithm_param)) {
  662. goto done;
  663. }
  664. /* X-Amz-Credential */
  665. struct aws_uri_param credential_param = {
  666. .key = aws_byte_cursor_from_string(g_aws_signing_credential_query_param_name),
  667. .value = aws_byte_cursor_from_buf(&state->access_credential_scope),
  668. };
  669. if (s_add_authorization_query_param(state, unencoded_query_params, &credential_param)) {
  670. goto done;
  671. }
  672. /* X-Amz-Date */
  673. struct aws_uri_param date_param = {
  674. .key = aws_byte_cursor_from_string(g_aws_signing_date_name),
  675. .value = aws_byte_cursor_from_buf(&state->date),
  676. };
  677. if (s_add_authorization_query_param(state, unencoded_query_params, &date_param)) {
  678. goto done;
  679. }
  680. /* X-Amz-SignedHeaders */
  681. struct aws_uri_param signed_headers_param = {
  682. .key = aws_byte_cursor_from_string(g_aws_signing_signed_headers_query_param_name),
  683. .value = aws_byte_cursor_from_buf(&state->signed_headers),
  684. };
  685. if (s_add_authorization_query_param(state, unencoded_query_params, &signed_headers_param)) {
  686. goto done;
  687. }
  688. /* X-Amz-Expires */
  689. uint64_t expiration_in_seconds = state->config.expiration_in_seconds;
  690. if (expiration_in_seconds > 0) {
  691. struct aws_uri_param expires_param = {
  692. .key = aws_byte_cursor_from_string(g_aws_signing_expires_query_param_name),
  693. .value = aws_byte_cursor_from_c_str(state->expiration_array),
  694. };
  695. if (s_add_authorization_query_param(state, unencoded_query_params, &expires_param)) {
  696. goto done;
  697. }
  698. }
  699. /* X-Amz-Security-token */
  700. struct aws_byte_cursor security_token_name_cur = aws_byte_cursor_from_string(g_aws_signing_security_token_name);
  701. struct aws_byte_cursor session_token_cursor = aws_credentials_get_session_token(state->config.credentials);
  702. if (session_token_cursor.len > 0) {
  703. struct aws_uri_param security_token_param = {
  704. .key = security_token_name_cur,
  705. .value = session_token_cursor,
  706. };
  707. /* If omit_session_token is true, then security token is added to the
  708. * final signing result, but is treated as "unsigned" and does not
  709. * contribute to the authorization signature */
  710. if (state->config.flags.omit_session_token) {
  711. if (s_add_query_param_to_signing_result(state, &security_token_param)) {
  712. goto done;
  713. }
  714. } else {
  715. if (s_add_authorization_query_param(state, unencoded_query_params, &security_token_param)) {
  716. goto done;
  717. }
  718. }
  719. }
  720. /* X-Amz-Region-Set */
  721. if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC) {
  722. struct aws_uri_param region_set_param = {
  723. .key = aws_byte_cursor_from_string(g_aws_signing_region_set_name),
  724. .value = state->config.region,
  725. };
  726. if (s_add_authorization_query_param(state, unencoded_query_params, &region_set_param)) {
  727. goto done;
  728. }
  729. }
  730. /* NOTE: Update MAX_AUTHORIZATION_QUERY_PARAM_COUNT if more params added */
  731. result = AWS_OP_SUCCESS;
  732. done:
  733. return result;
  734. }
  735. static int s_validate_query_params(struct aws_array_list *unencoded_query_params) {
  736. const size_t param_count = aws_array_list_length(unencoded_query_params);
  737. for (size_t i = 0; i < param_count; ++i) {
  738. struct aws_uri_param param;
  739. AWS_ZERO_STRUCT(param);
  740. aws_array_list_get_at(unencoded_query_params, &param, i);
  741. struct aws_hash_element *forbidden_element = NULL;
  742. aws_hash_table_find(&s_forbidden_params, &param.key, &forbidden_element);
  743. if (forbidden_element != NULL) {
  744. AWS_LOGF_ERROR(
  745. AWS_LS_AUTH_SIGNING,
  746. "AWS authorization query param \"" PRInSTR "\" found in request while signing",
  747. AWS_BYTE_CURSOR_PRI(param.key));
  748. return aws_raise_error(AWS_AUTH_SIGNING_ILLEGAL_REQUEST_QUERY_PARAM);
  749. }
  750. }
  751. return AWS_OP_SUCCESS;
  752. }
  753. /**
  754. * Apply or remove URI-encoding to each aws_uri_param in a list.
  755. * (new strings are added to temp_strings)
  756. * Append function must grow buffer if necessary.
  757. */
  758. static int s_transform_query_params(
  759. struct aws_signing_state_aws *state,
  760. struct aws_array_list *param_list,
  761. struct aws_array_list *temp_strings,
  762. int (*byte_buf_append_dynamic_param_fn)(struct aws_byte_buf *, const struct aws_byte_cursor *)) {
  763. const size_t param_count = aws_array_list_length(param_list);
  764. struct aws_uri_param *param = NULL;
  765. for (size_t i = 0; i < param_count; ++i) {
  766. aws_array_list_get_at_ptr(param_list, (void **)&param, i);
  767. /* encode/decode key and save string */
  768. state->scratch_buf.len = 0;
  769. if (byte_buf_append_dynamic_param_fn(&state->scratch_buf, &param->key)) {
  770. return AWS_OP_ERR;
  771. }
  772. struct aws_string *key_str = aws_string_new_from_buf(state->allocator, &state->scratch_buf);
  773. if (!key_str) {
  774. return AWS_OP_ERR;
  775. }
  776. if (aws_array_list_push_back(temp_strings, &key_str)) {
  777. aws_string_destroy(key_str);
  778. return AWS_OP_ERR;
  779. }
  780. /* encode/decode value and save string */
  781. state->scratch_buf.len = 0;
  782. if (byte_buf_append_dynamic_param_fn(&state->scratch_buf, &param->value)) {
  783. return AWS_OP_ERR;
  784. }
  785. struct aws_string *value_str = aws_string_new_from_buf(state->allocator, &state->scratch_buf);
  786. if (!value_str) {
  787. return AWS_OP_ERR;
  788. }
  789. if (aws_array_list_push_back(temp_strings, &value_str)) {
  790. aws_string_destroy(value_str);
  791. return AWS_OP_ERR;
  792. }
  793. /* save encoded/decoded param */
  794. param->key = aws_byte_cursor_from_string(key_str);
  795. param->value = aws_byte_cursor_from_string(value_str);
  796. }
  797. return AWS_OP_SUCCESS;
  798. }
  799. /*
  800. * Adds the full canonical query string to the canonical request.
  801. * Note that aws-c-auth takes query params from the URI, so they should already be URI-encoded.
  802. * To ensure that the signature uses "canonical" URI-encoding, we decode and then re-encode the params.
  803. */
  804. static int s_append_canonical_query_string(struct aws_uri *uri, struct aws_signing_state_aws *state) {
  805. struct aws_allocator *allocator = state->allocator;
  806. struct aws_byte_buf *canonical_request_buffer = &state->canonical_request;
  807. int result = AWS_OP_ERR;
  808. struct aws_array_list query_params;
  809. AWS_ZERO_STRUCT(query_params);
  810. struct aws_array_list temp_strings;
  811. AWS_ZERO_STRUCT(temp_strings);
  812. /* Determine max number of query parameters.
  813. * If none, skip to end of function */
  814. size_t max_param_count = 0;
  815. struct aws_uri_param param_i;
  816. AWS_ZERO_STRUCT(param_i);
  817. while (aws_uri_query_string_next_param(uri, &param_i)) {
  818. ++max_param_count;
  819. }
  820. if (state->config.signature_type == AWS_ST_HTTP_REQUEST_QUERY_PARAMS) {
  821. max_param_count += MAX_AUTHORIZATION_QUERY_PARAM_COUNT;
  822. }
  823. if (max_param_count == 0) {
  824. goto finish;
  825. }
  826. /* Allocate storage for mutable list of query params */
  827. if (aws_array_list_init_dynamic(&query_params, allocator, max_param_count, sizeof(struct aws_uri_param))) {
  828. goto cleanup;
  829. }
  830. /* Allocate storage for both the decoded, and re-encoded, key and value strings */
  831. if (aws_array_list_init_dynamic(
  832. &temp_strings, state->allocator, max_param_count * 4, sizeof(struct aws_string *))) {
  833. goto cleanup;
  834. }
  835. /* Get existing query params */
  836. if (aws_uri_query_string_params(uri, &query_params)) {
  837. goto cleanup;
  838. }
  839. /* Remove URI-encoding */
  840. if (s_transform_query_params(state, &query_params, &temp_strings, aws_byte_buf_append_decoding_uri)) {
  841. goto cleanup;
  842. }
  843. /* Validate existing query params */
  844. if (s_validate_query_params(&query_params)) {
  845. goto cleanup;
  846. }
  847. /* Add authorization query params */
  848. if (s_add_authorization_query_params(state, &query_params)) {
  849. goto cleanup;
  850. }
  851. /* Apply canonical URI-encoding to the query params */
  852. if (s_transform_query_params(state, &query_params, &temp_strings, aws_byte_buf_append_encoding_uri_param)) {
  853. goto cleanup;
  854. }
  855. const size_t param_count = aws_array_list_length(&query_params);
  856. /* Sort the encoded params and append to canonical request */
  857. qsort(query_params.data, param_count, sizeof(struct aws_uri_param), s_canonical_query_param_comparator);
  858. for (size_t i = 0; i < param_count; ++i) {
  859. struct aws_uri_param param;
  860. AWS_ZERO_STRUCT(param);
  861. if (aws_array_list_get_at(&query_params, &param, i)) {
  862. goto cleanup;
  863. }
  864. if (s_append_canonical_query_param(&param, canonical_request_buffer)) {
  865. goto cleanup;
  866. }
  867. if (i + 1 < param_count) {
  868. if (aws_byte_buf_append_byte_dynamic(canonical_request_buffer, '&')) {
  869. goto cleanup;
  870. }
  871. }
  872. }
  873. finish:
  874. if (aws_byte_buf_append_byte_dynamic(canonical_request_buffer, '\n')) {
  875. goto cleanup;
  876. }
  877. result = AWS_OP_SUCCESS;
  878. cleanup:
  879. aws_array_list_clean_up(&query_params);
  880. if (aws_array_list_is_valid(&temp_strings)) {
  881. const size_t string_count = aws_array_list_length(&temp_strings);
  882. for (size_t i = 0; i < string_count; ++i) {
  883. struct aws_string *string = NULL;
  884. aws_array_list_get_at(&temp_strings, &string, i);
  885. aws_string_destroy(string);
  886. }
  887. aws_array_list_clean_up(&temp_strings);
  888. }
  889. return result;
  890. }
  891. /*
  892. * It is unclear from the spec (and not resolved by the tests) whether other forms of whitespace (\t \v) should be
  893. * included in the trimming done to headers
  894. */
  895. static bool s_is_space(uint8_t value) {
  896. return aws_isspace(value);
  897. }
  898. /*
  899. * Appends a single header key-value pair to the canonical request. Multi-line and repeat headers make this more
  900. * complicated than you'd expect.
  901. *
  902. * We call this function on a sorted collection, so header repeats are guaranteed to be consecutive.
  903. *
  904. * In particular, there are two cases:
  905. * (1) This is a header whose name hasn't been seen before, in which case we start a new line and append both name and
  906. * value. (2) This is a header we've previously seen, just append the value.
  907. *
  908. * The fact that we can't '\n' until we've moved to a new header name also complicates the logic.
  909. *
  910. * This function appends to a state buffer rather than the canonical request. This allows us to calculate the signed
  911. * headers (so that it can go into the query param if needed) before the query params are put into the canonical
  912. * request.
  913. */
  914. static int s_append_canonical_header(
  915. struct aws_signing_state_aws *state,
  916. struct aws_signable_property_list_pair *header,
  917. const struct aws_byte_cursor *last_seen_header_name) {
  918. struct aws_byte_buf *canonical_header_buffer = &state->canonical_header_block;
  919. struct aws_byte_buf *signed_headers_buffer = &state->signed_headers;
  920. const uint8_t *to_lower_table = aws_lookup_table_to_lower_get();
  921. /*
  922. * Write to the signed_headers shared state for later use, copy
  923. * to canonical header buffer as well
  924. */
  925. if (last_seen_header_name == NULL ||
  926. aws_byte_cursor_compare_lookup(last_seen_header_name, &header->name, aws_lookup_table_to_lower_get()) != 0) {
  927. /*
  928. * The headers arrive in sorted order, so we know we've never seen this header before
  929. */
  930. if (last_seen_header_name) {
  931. /*
  932. * there's a previous header, add appropriate separator in both canonical header buffer
  933. * and signed headers buffer
  934. */
  935. if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, '\n')) {
  936. return AWS_OP_ERR;
  937. }
  938. if (aws_byte_buf_append_byte_dynamic(signed_headers_buffer, ';')) {
  939. return AWS_OP_ERR;
  940. }
  941. }
  942. /* add it to the signed headers buffer */
  943. if (s_append_with_lookup(signed_headers_buffer, &header->name, to_lower_table)) {
  944. return AWS_OP_ERR;
  945. }
  946. /* add it to the canonical header buffer */
  947. if (s_append_with_lookup(canonical_header_buffer, &header->name, to_lower_table)) {
  948. return AWS_OP_ERR;
  949. }
  950. if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, ':')) {
  951. return AWS_OP_ERR;
  952. }
  953. } else {
  954. /* we've seen this header before, add a comma before appending the value */
  955. if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, ',')) {
  956. return AWS_OP_ERR;
  957. }
  958. }
  959. /*
  960. * This is the unsafe, non-append write of the header value where consecutive whitespace
  961. * is squashed into a single space. Since this can only shrink the value length and we've
  962. * already reserved enough to hold the value, we can do raw buffer writes safely without
  963. * worrying about capacity.
  964. */
  965. struct aws_byte_cursor trimmed_value = aws_byte_cursor_trim_pred(&header->value, s_is_space);
  966. /* raw, unsafe write loop */
  967. bool in_space = false;
  968. uint8_t *start_ptr = trimmed_value.ptr;
  969. uint8_t *end_ptr = trimmed_value.ptr + trimmed_value.len;
  970. uint8_t *dest_ptr = canonical_header_buffer->buffer + canonical_header_buffer->len;
  971. while (start_ptr < end_ptr) {
  972. uint8_t value = *start_ptr;
  973. bool is_space = s_is_space(value);
  974. if (is_space) {
  975. value = ' ';
  976. }
  977. if (!is_space || !in_space) {
  978. *dest_ptr++ = value;
  979. ++canonical_header_buffer->len;
  980. }
  981. in_space = is_space;
  982. ++start_ptr;
  983. }
  984. return AWS_OP_SUCCESS;
  985. }
  986. /* Add header to stable_header_list to be canonicalized, and also to final signing result */
  987. static int s_add_authorization_header(
  988. struct aws_signing_state_aws *state,
  989. struct aws_array_list *stable_header_list,
  990. size_t *out_required_capacity,
  991. struct aws_byte_cursor name,
  992. struct aws_byte_cursor value) {
  993. /* Add to stable_header_list to be canonicalized */
  994. struct stable_header stable_header = {
  995. .original_index = aws_array_list_length(stable_header_list),
  996. .header =
  997. {
  998. .name = name,
  999. .value = value,
  1000. },
  1001. };
  1002. if (aws_array_list_push_back(stable_header_list, &stable_header)) {
  1003. return AWS_OP_ERR;
  1004. }
  1005. /* Add to signing result */
  1006. if (aws_signing_result_append_property_list(&state->result, g_aws_http_headers_property_list_name, &name, &value)) {
  1007. return AWS_OP_ERR;
  1008. }
  1009. *out_required_capacity += name.len + value.len;
  1010. return AWS_OP_SUCCESS;
  1011. }
  1012. /*
  1013. * Builds the list of header name-value pairs to be added to the canonical request. The list members are
  1014. * actually the header wrapper structs that allow for stable sorting.
  1015. *
  1016. * Takes the original request headers, adds X-Amz-Date, and optionally, x-amz-content-sha256
  1017. *
  1018. * If we add filtering/exclusion support, this is where it would go
  1019. */
  1020. static int s_build_canonical_stable_header_list(
  1021. struct aws_signing_state_aws *state,
  1022. struct aws_array_list *stable_header_list,
  1023. size_t *out_required_capacity) {
  1024. AWS_ASSERT(aws_array_list_length(stable_header_list) == 0);
  1025. *out_required_capacity = 0;
  1026. const struct aws_signable *signable = state->signable;
  1027. /*
  1028. * request headers
  1029. */
  1030. struct aws_array_list *signable_header_list = NULL;
  1031. if (aws_signable_get_property_list(signable, g_aws_http_headers_property_list_name, &signable_header_list)) {
  1032. return AWS_OP_ERR;
  1033. }
  1034. const size_t signable_header_count = aws_array_list_length(signable_header_list);
  1035. for (size_t i = 0; i < signable_header_count; ++i) {
  1036. struct stable_header header_wrapper;
  1037. AWS_ZERO_STRUCT(header_wrapper);
  1038. header_wrapper.original_index = i;
  1039. if (aws_array_list_get_at(signable_header_list, &header_wrapper.header, i)) {
  1040. return AWS_OP_ERR;
  1041. }
  1042. struct aws_byte_cursor *header_name_cursor = &header_wrapper.header.name;
  1043. if (!s_should_sign_header(state, header_name_cursor)) {
  1044. continue;
  1045. }
  1046. *out_required_capacity += header_wrapper.header.name.len + header_wrapper.header.value.len;
  1047. if (aws_array_list_push_back(stable_header_list, &header_wrapper)) {
  1048. return AWS_OP_ERR;
  1049. }
  1050. }
  1051. /* If doing HEADERS signature type, add required X-Amz-*** headers.
  1052. * NOTE: For QUERY_PARAMS signature type, X-Amz-*** params are added to query string instead. */
  1053. if (state->config.signature_type == AWS_ST_HTTP_REQUEST_HEADERS) {
  1054. /*
  1055. * X-Amz-Security-Token
  1056. */
  1057. struct aws_byte_cursor session_token_cursor = aws_credentials_get_session_token(state->config.credentials);
  1058. if (session_token_cursor.len > 0) {
  1059. /* Note that if omit_session_token is true, it is added to final
  1060. * signing result but NOT included in canonicalized headers. */
  1061. if (state->config.flags.omit_session_token) {
  1062. if (aws_signing_result_append_property_list(
  1063. &state->result,
  1064. g_aws_http_headers_property_list_name,
  1065. &s_amz_security_token_header_name,
  1066. &session_token_cursor)) {
  1067. return AWS_OP_ERR;
  1068. }
  1069. } else {
  1070. if (s_add_authorization_header(
  1071. state,
  1072. stable_header_list,
  1073. out_required_capacity,
  1074. s_amz_security_token_header_name,
  1075. session_token_cursor)) {
  1076. return AWS_OP_ERR;
  1077. }
  1078. }
  1079. }
  1080. /*
  1081. * X-Amz-Date
  1082. */
  1083. if (s_add_authorization_header(
  1084. state,
  1085. stable_header_list,
  1086. out_required_capacity,
  1087. s_amz_date_header_name,
  1088. aws_byte_cursor_from_buf(&state->date))) {
  1089. return AWS_OP_ERR;
  1090. }
  1091. *out_required_capacity += g_aws_signing_date_name->len + state->date.len;
  1092. /*
  1093. * x-amz-region-set
  1094. */
  1095. if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC) {
  1096. if (s_add_authorization_header(
  1097. state,
  1098. stable_header_list,
  1099. out_required_capacity,
  1100. aws_byte_cursor_from_string(g_aws_signing_region_set_name),
  1101. state->config.region)) {
  1102. return AWS_OP_ERR;
  1103. }
  1104. }
  1105. /*
  1106. * x-amz-content-sha256 (optional)
  1107. */
  1108. if (state->config.signed_body_header == AWS_SBHT_X_AMZ_CONTENT_SHA256) {
  1109. if (s_add_authorization_header(
  1110. state,
  1111. stable_header_list,
  1112. out_required_capacity,
  1113. s_amz_content_sha256_header_name,
  1114. aws_byte_cursor_from_buf(&state->payload_hash))) {
  1115. return AWS_OP_ERR;
  1116. }
  1117. }
  1118. /* NOTE: Update MAX_AUTHORIZATION_HEADER_COUNT if more headers added */
  1119. }
  1120. *out_required_capacity += aws_array_list_length(stable_header_list) * 2; /* ':' + '\n' per header */
  1121. return AWS_OP_SUCCESS;
  1122. }
  1123. static int s_validate_signable_header_list(struct aws_array_list *header_list) {
  1124. const size_t header_count = aws_array_list_length(header_list);
  1125. for (size_t i = 0; i < header_count; ++i) {
  1126. struct aws_signable_property_list_pair header;
  1127. AWS_ZERO_STRUCT(header);
  1128. aws_array_list_get_at(header_list, &header, i);
  1129. struct aws_hash_element *forbidden_element = NULL;
  1130. aws_hash_table_find(&s_forbidden_headers, &header.name, &forbidden_element);
  1131. if (forbidden_element != NULL) {
  1132. AWS_LOGF_ERROR(
  1133. AWS_LS_AUTH_SIGNING,
  1134. "AWS authorization header \"" PRInSTR "\" found in request while signing",
  1135. AWS_BYTE_CURSOR_PRI(header.name));
  1136. return aws_raise_error(AWS_AUTH_SIGNING_ILLEGAL_REQUEST_HEADER);
  1137. }
  1138. }
  1139. return AWS_OP_SUCCESS;
  1140. }
  1141. static int s_canonicalize_headers(struct aws_signing_state_aws *state) {
  1142. const struct aws_signable *signable = state->signable;
  1143. struct aws_allocator *allocator = state->allocator;
  1144. struct aws_byte_buf *header_buffer = &state->canonical_header_block;
  1145. AWS_ASSERT(header_buffer->len == 0);
  1146. int result = AWS_OP_ERR;
  1147. struct aws_array_list *signable_header_list = NULL;
  1148. if (aws_signable_get_property_list(signable, g_aws_http_headers_property_list_name, &signable_header_list)) {
  1149. return AWS_OP_ERR;
  1150. }
  1151. if (s_validate_signable_header_list(signable_header_list)) {
  1152. return AWS_OP_ERR;
  1153. }
  1154. const size_t signable_header_count = aws_array_list_length(signable_header_list);
  1155. /* Overestimate capacity to avoid re-allocation */
  1156. size_t headers_reserve_count = signable_header_count + MAX_AUTHORIZATION_HEADER_COUNT;
  1157. struct aws_array_list headers;
  1158. if (aws_array_list_init_dynamic(&headers, allocator, headers_reserve_count, sizeof(struct stable_header))) {
  1159. return AWS_OP_ERR;
  1160. }
  1161. size_t header_buffer_reserve_size = 0;
  1162. if (s_build_canonical_stable_header_list(state, &headers, &header_buffer_reserve_size)) {
  1163. goto on_cleanup;
  1164. }
  1165. /*
  1166. * Make sure there's enough room in the request buffer to hold a conservative overestimate of the room
  1167. * needed for canonical headers. There are places we'll be using an append function that does not resize.
  1168. */
  1169. if (aws_byte_buf_reserve(header_buffer, header_buffer_reserve_size)) {
  1170. return AWS_OP_ERR;
  1171. }
  1172. const size_t header_count = aws_array_list_length(&headers);
  1173. /* Sort the arraylist via lowercase header name and original position */
  1174. qsort(headers.data, header_count, sizeof(struct stable_header), s_canonical_header_comparator);
  1175. /* Iterate the sorted list, writing the canonical representation into the request */
  1176. struct aws_byte_cursor *last_seen_header_name = NULL;
  1177. for (size_t i = 0; i < header_count; ++i) {
  1178. struct stable_header *wrapper = NULL;
  1179. if (aws_array_list_get_at_ptr(&headers, (void **)&wrapper, i)) {
  1180. goto on_cleanup;
  1181. }
  1182. if (s_append_canonical_header(state, &wrapper->header, last_seen_header_name)) {
  1183. goto on_cleanup;
  1184. }
  1185. last_seen_header_name = &wrapper->header.name;
  1186. }
  1187. /* check for count greater than zero in case someone attempts to canonicalize an empty list of trailing headers */
  1188. /* There's always at least one header entry (X-Amz-Date), end the last one */
  1189. if (header_count > 0) {
  1190. if (aws_byte_buf_append_byte_dynamic(header_buffer, '\n')) {
  1191. return AWS_OP_ERR;
  1192. }
  1193. }
  1194. result = AWS_OP_SUCCESS;
  1195. on_cleanup:
  1196. aws_array_list_clean_up(&headers);
  1197. return result;
  1198. }
  1199. static int s_append_signed_headers(struct aws_signing_state_aws *state) {
  1200. struct aws_byte_buf *header_buffer = &state->canonical_header_block;
  1201. struct aws_byte_buf *signed_headers_buffer = &state->signed_headers;
  1202. if (aws_byte_buf_append_byte_dynamic(header_buffer, '\n')) {
  1203. return AWS_OP_ERR;
  1204. }
  1205. struct aws_byte_cursor signed_headers_cursor = aws_byte_cursor_from_buf(signed_headers_buffer);
  1206. if (aws_byte_buf_append_dynamic(header_buffer, &signed_headers_cursor)) {
  1207. return AWS_OP_ERR;
  1208. }
  1209. if (aws_byte_buf_append_byte_dynamic(header_buffer, '\n')) {
  1210. return AWS_OP_ERR;
  1211. }
  1212. return AWS_OP_SUCCESS;
  1213. }
  1214. /*
  1215. * Top-level-ish function to write the canonical header set into a buffer as well as the signed header names
  1216. * into a separate buffer. We do this very early in the canonical request construction process so that the
  1217. * query params processing has the signed header names available to it.
  1218. */
  1219. static int s_build_canonical_headers(struct aws_signing_state_aws *state) {
  1220. if (s_canonicalize_headers(state)) {
  1221. return AWS_OP_ERR;
  1222. }
  1223. if (s_append_signed_headers(state)) {
  1224. return AWS_OP_ERR;
  1225. }
  1226. return AWS_OP_SUCCESS;
  1227. }
  1228. /*
  1229. * Computes the canonical request payload value.
  1230. */
  1231. static int s_build_canonical_payload(struct aws_signing_state_aws *state) {
  1232. const struct aws_signable *signable = state->signable;
  1233. struct aws_allocator *allocator = state->allocator;
  1234. struct aws_byte_buf *payload_hash_buffer = &state->payload_hash;
  1235. AWS_ASSERT(payload_hash_buffer->len == 0);
  1236. struct aws_byte_buf body_buffer;
  1237. AWS_ZERO_STRUCT(body_buffer);
  1238. struct aws_byte_buf digest_buffer;
  1239. AWS_ZERO_STRUCT(digest_buffer);
  1240. struct aws_hash *hash = NULL;
  1241. int result = AWS_OP_ERR;
  1242. if (state->config.signed_body_value.len == 0) {
  1243. /* No value provided by user, so we must calculate it */
  1244. hash = aws_sha256_new(allocator);
  1245. if (hash == NULL) {
  1246. return AWS_OP_ERR;
  1247. }
  1248. if (aws_byte_buf_init(&body_buffer, allocator, BODY_READ_BUFFER_SIZE) ||
  1249. aws_byte_buf_init(&digest_buffer, allocator, AWS_SHA256_LEN)) {
  1250. goto on_cleanup;
  1251. }
  1252. struct aws_input_stream *payload_stream = NULL;
  1253. if (aws_signable_get_payload_stream(signable, &payload_stream)) {
  1254. goto on_cleanup;
  1255. }
  1256. if (payload_stream != NULL) {
  1257. if (aws_input_stream_seek(payload_stream, 0, AWS_SSB_BEGIN)) {
  1258. goto on_cleanup;
  1259. }
  1260. struct aws_stream_status payload_status;
  1261. AWS_ZERO_STRUCT(payload_status);
  1262. while (!payload_status.is_end_of_stream) {
  1263. /* reset the temporary body buffer; we can calculate the hash in window chunks */
  1264. body_buffer.len = 0;
  1265. if (aws_input_stream_read(payload_stream, &body_buffer)) {
  1266. goto on_cleanup;
  1267. }
  1268. if (body_buffer.len > 0) {
  1269. struct aws_byte_cursor body_cursor = aws_byte_cursor_from_buf(&body_buffer);
  1270. aws_hash_update(hash, &body_cursor);
  1271. }
  1272. if (aws_input_stream_get_status(payload_stream, &payload_status)) {
  1273. goto on_cleanup;
  1274. }
  1275. }
  1276. /* reset the input stream for sending */
  1277. if (aws_input_stream_seek(payload_stream, 0, AWS_SSB_BEGIN)) {
  1278. goto on_cleanup;
  1279. }
  1280. }
  1281. if (aws_hash_finalize(hash, &digest_buffer, 0)) {
  1282. goto on_cleanup;
  1283. }
  1284. struct aws_byte_cursor digest_cursor = aws_byte_cursor_from_buf(&digest_buffer);
  1285. if (aws_hex_encode_append_dynamic(&digest_cursor, payload_hash_buffer)) {
  1286. goto on_cleanup;
  1287. }
  1288. } else {
  1289. /* Use value provided in config */
  1290. if (aws_byte_buf_append_dynamic(payload_hash_buffer, &state->config.signed_body_value)) {
  1291. goto on_cleanup;
  1292. }
  1293. }
  1294. result = AWS_OP_SUCCESS;
  1295. on_cleanup:
  1296. aws_byte_buf_clean_up(&digest_buffer);
  1297. aws_byte_buf_clean_up(&body_buffer);
  1298. if (hash) {
  1299. aws_hash_destroy(hash);
  1300. }
  1301. return result;
  1302. }
  1303. /*
  1304. * Copies the previously-computed payload hash into the canonical request buffer
  1305. */
  1306. static int s_append_canonical_payload_hash(struct aws_signing_state_aws *state) {
  1307. struct aws_byte_buf *canonical_request_buffer = &state->canonical_request;
  1308. struct aws_byte_buf *payload_hash_buffer = &state->payload_hash;
  1309. /*
  1310. * Copy the hex-encoded payload hash into the canonical request
  1311. */
  1312. struct aws_byte_cursor payload_hash_cursor = aws_byte_cursor_from_buf(payload_hash_buffer);
  1313. if (aws_byte_buf_append_dynamic(canonical_request_buffer, &payload_hash_cursor)) {
  1314. return AWS_OP_ERR;
  1315. }
  1316. /* Sigv4 spec claims a newline should be included after the payload, but the implementation doesn't do this */
  1317. return AWS_OP_SUCCESS;
  1318. }
  1319. AWS_STATIC_STRING_FROM_LITERAL(s_credential_scope_sigv4_terminator, "aws4_request");
  1320. static int s_append_credential_scope_terminator(enum aws_signing_algorithm algorithm, struct aws_byte_buf *dest) {
  1321. struct aws_byte_cursor terminator_cursor;
  1322. switch (algorithm) {
  1323. case AWS_SIGNING_ALGORITHM_V4:
  1324. case AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC:
  1325. terminator_cursor = aws_byte_cursor_from_string(s_credential_scope_sigv4_terminator);
  1326. break;
  1327. default:
  1328. return aws_raise_error(AWS_AUTH_SIGNING_UNSUPPORTED_ALGORITHM);
  1329. }
  1330. return aws_byte_buf_append_dynamic(dest, &terminator_cursor);
  1331. }
  1332. /*
  1333. * Builds the credential scope string by appending a bunch of things together:
  1334. * Date, region, service, algorithm terminator
  1335. */
  1336. static int s_build_credential_scope(struct aws_signing_state_aws *state) {
  1337. AWS_ASSERT(state->credential_scope.len == 0);
  1338. const struct aws_signing_config_aws *config = &state->config;
  1339. struct aws_byte_buf *dest = &state->credential_scope;
  1340. /*
  1341. * date output uses the non-dynamic append, so make sure there's enough room first
  1342. */
  1343. if (aws_byte_buf_reserve_relative(dest, AWS_DATE_TIME_STR_MAX_LEN)) {
  1344. return AWS_OP_ERR;
  1345. }
  1346. if (aws_date_time_to_utc_time_short_str(&config->date, AWS_DATE_FORMAT_ISO_8601_BASIC, dest)) {
  1347. return AWS_OP_ERR;
  1348. }
  1349. if (aws_byte_buf_append_byte_dynamic(dest, '/')) {
  1350. return AWS_OP_ERR;
  1351. }
  1352. if (config->algorithm != AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC) {
  1353. if (aws_byte_buf_append_dynamic(dest, &config->region)) {
  1354. return AWS_OP_ERR;
  1355. }
  1356. if (aws_byte_buf_append_byte_dynamic(dest, '/')) {
  1357. return AWS_OP_ERR;
  1358. }
  1359. }
  1360. if (aws_byte_buf_append_dynamic(dest, &config->service)) {
  1361. return AWS_OP_ERR;
  1362. }
  1363. if (aws_byte_buf_append_byte_dynamic(dest, '/')) {
  1364. return AWS_OP_ERR;
  1365. }
  1366. if (s_append_credential_scope_terminator(state->config.algorithm, dest)) {
  1367. return AWS_OP_ERR;
  1368. }
  1369. /* While we're at it, build the accesskey/credential scope string which is used during query param signing*/
  1370. struct aws_byte_cursor access_key_cursor = aws_credentials_get_access_key_id(state->config.credentials);
  1371. if (aws_byte_buf_append_dynamic(&state->access_credential_scope, &access_key_cursor)) {
  1372. return AWS_OP_ERR;
  1373. }
  1374. if (aws_byte_buf_append_byte_dynamic(&state->access_credential_scope, '/')) {
  1375. return AWS_OP_ERR;
  1376. }
  1377. struct aws_byte_cursor credential_scope_cursor = aws_byte_cursor_from_buf(&state->credential_scope);
  1378. if (aws_byte_buf_append_dynamic(&state->access_credential_scope, &credential_scope_cursor)) {
  1379. return AWS_OP_ERR;
  1380. }
  1381. return AWS_OP_SUCCESS;
  1382. }
  1383. /*
  1384. * Hashes the canonical request and stores its hex representation
  1385. */
  1386. static int s_build_canonical_request_hash(struct aws_signing_state_aws *state) {
  1387. struct aws_allocator *allocator = state->allocator;
  1388. struct aws_byte_buf *dest = &state->string_to_sign_payload;
  1389. int result = AWS_OP_ERR;
  1390. struct aws_byte_buf digest_buffer;
  1391. AWS_ZERO_STRUCT(digest_buffer);
  1392. if (aws_byte_buf_init(&digest_buffer, allocator, AWS_SHA256_LEN)) {
  1393. goto cleanup;
  1394. }
  1395. struct aws_byte_cursor canonical_request_cursor = aws_byte_cursor_from_buf(&state->canonical_request);
  1396. if (aws_sha256_compute(allocator, &canonical_request_cursor, &digest_buffer, 0)) {
  1397. goto cleanup;
  1398. }
  1399. struct aws_byte_cursor digest_cursor = aws_byte_cursor_from_buf(&digest_buffer);
  1400. if (aws_hex_encode_append_dynamic(&digest_cursor, dest)) {
  1401. goto cleanup;
  1402. }
  1403. result = AWS_OP_SUCCESS;
  1404. cleanup:
  1405. aws_byte_buf_clean_up(&digest_buffer);
  1406. return result;
  1407. }
  1408. /**
  1409. * Note that there is no canonical request for event signing.
  1410. * The string to sign for events is detailed here:
  1411. * https://docs.aws.amazon.com/transcribe/latest/dg/streaming-http2.html
  1412. *
  1413. * String stringToSign =
  1414. * "AWS4-HMAC-SHA256" +
  1415. * "\n" +
  1416. * DateTime +
  1417. * "\n" +
  1418. * Keypath +
  1419. * "\n" +
  1420. * Hex(priorSignature) +
  1421. * "\n" +
  1422. * HexHash(nonSignatureHeaders) +
  1423. * "\n" +
  1424. * HexHash(payload);
  1425. *
  1426. * This function will build the string_to_sign_payload,
  1427. * aka "everything after the Keypath line in the string to sign".
  1428. */
  1429. static int s_build_string_to_sign_payload_for_event(struct aws_signing_state_aws *state) {
  1430. int result = AWS_OP_ERR;
  1431. struct aws_byte_buf *dest = &state->string_to_sign_payload;
  1432. /*
  1433. * Hex(priorSignature) + "\n"
  1434. *
  1435. * Fortunately, the prior signature is already hex.
  1436. */
  1437. struct aws_byte_cursor prev_signature_cursor;
  1438. AWS_ZERO_STRUCT(prev_signature_cursor);
  1439. if (aws_signable_get_property(state->signable, g_aws_previous_signature_property_name, &prev_signature_cursor)) {
  1440. AWS_LOGF_ERROR(
  1441. AWS_LS_AUTH_SIGNING, "(id=%p) Event signable missing previous signature property", (void *)state->signable);
  1442. return aws_raise_error(AWS_AUTH_SIGNING_MISSING_PREVIOUS_SIGNATURE);
  1443. }
  1444. /* strip any padding (AWS_SIGV4A_SIGNATURE_PADDING_BYTE) from the previous signature */
  1445. prev_signature_cursor = aws_trim_padded_sigv4a_signature(prev_signature_cursor);
  1446. if (aws_byte_buf_append_dynamic(dest, &prev_signature_cursor)) {
  1447. return AWS_OP_ERR;
  1448. }
  1449. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1450. return AWS_OP_ERR;
  1451. }
  1452. /*
  1453. * HexHash(nonSignatureHeaders) + "\n"
  1454. *
  1455. * nonSignatureHeaders is just the ":date" header.
  1456. * We need to encode these headers in event-stream format, as described here:
  1457. * https://docs.aws.amazon.com/transcribe/latest/dg/streaming-setting-up.html
  1458. *
  1459. * | Header Name Length | Header Name | Header Value Type | Header Value Length | Header Value |
  1460. * | 1 byte | N bytes | 1 byte | 2 bytes | N bytes |
  1461. */
  1462. struct aws_byte_buf date_buffer;
  1463. AWS_ZERO_STRUCT(date_buffer);
  1464. struct aws_byte_buf digest_buffer;
  1465. AWS_ZERO_STRUCT(digest_buffer);
  1466. if (aws_byte_buf_init(&date_buffer, state->allocator, 15)) {
  1467. goto cleanup;
  1468. }
  1469. struct aws_byte_cursor header_name = aws_byte_cursor_from_c_str(":date");
  1470. AWS_FATAL_ASSERT(aws_byte_buf_write_u8(&date_buffer, (uint8_t)header_name.len));
  1471. if (aws_byte_buf_append_dynamic(&date_buffer, &header_name)) {
  1472. goto cleanup;
  1473. }
  1474. /* Type of timestamp header */
  1475. AWS_FATAL_ASSERT(aws_byte_buf_write_u8(&date_buffer, 8 /*AWS_EVENT_STREAM_HEADER_TIMESTAMP*/));
  1476. AWS_FATAL_ASSERT(aws_byte_buf_write_be64(&date_buffer, (int64_t)aws_date_time_as_millis(&state->config.date)));
  1477. /* calculate sha 256 of encoded buffer */
  1478. if (aws_byte_buf_init(&digest_buffer, state->allocator, AWS_SHA256_LEN)) {
  1479. goto cleanup;
  1480. }
  1481. struct aws_byte_cursor date_cursor = aws_byte_cursor_from_buf(&date_buffer);
  1482. if (aws_sha256_compute(state->allocator, &date_cursor, &digest_buffer, 0)) {
  1483. goto cleanup;
  1484. }
  1485. struct aws_byte_cursor digest_cursor = aws_byte_cursor_from_buf(&digest_buffer);
  1486. if (aws_hex_encode_append_dynamic(&digest_cursor, dest)) {
  1487. goto cleanup;
  1488. }
  1489. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1490. goto cleanup;
  1491. }
  1492. /*
  1493. * HexHash(payload);
  1494. *
  1495. * The payload was already hashed in an earlier stage
  1496. */
  1497. struct aws_byte_cursor current_chunk_hash_cursor = aws_byte_cursor_from_buf(&state->payload_hash);
  1498. if (aws_byte_buf_append_dynamic(dest, &current_chunk_hash_cursor)) {
  1499. goto cleanup;
  1500. }
  1501. result = AWS_OP_SUCCESS;
  1502. cleanup:
  1503. aws_byte_buf_clean_up(&date_buffer);
  1504. aws_byte_buf_clean_up(&digest_buffer);
  1505. return result;
  1506. }
  1507. static int s_build_canonical_request_body_chunk(struct aws_signing_state_aws *state) {
  1508. struct aws_byte_buf *dest = &state->string_to_sign_payload;
  1509. /* previous signature + \n */
  1510. struct aws_byte_cursor prev_signature_cursor;
  1511. AWS_ZERO_STRUCT(prev_signature_cursor);
  1512. if (aws_signable_get_property(state->signable, g_aws_previous_signature_property_name, &prev_signature_cursor)) {
  1513. AWS_LOGF_ERROR(
  1514. AWS_LS_AUTH_SIGNING, "(id=%p) Chunk signable missing previous signature property", (void *)state->signable);
  1515. return aws_raise_error(AWS_AUTH_SIGNING_MISSING_PREVIOUS_SIGNATURE);
  1516. }
  1517. /* strip any padding (AWS_SIGV4A_SIGNATURE_PADDING_BYTE) from the previous signature */
  1518. prev_signature_cursor = aws_trim_padded_sigv4a_signature(prev_signature_cursor);
  1519. if (aws_byte_buf_append_dynamic(dest, &prev_signature_cursor)) {
  1520. return AWS_OP_ERR;
  1521. }
  1522. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1523. return AWS_OP_ERR;
  1524. }
  1525. /* empty hash + \n */
  1526. if (aws_byte_buf_append_dynamic(dest, &g_aws_signed_body_value_empty_sha256)) {
  1527. return AWS_OP_ERR;
  1528. }
  1529. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1530. return AWS_OP_ERR;
  1531. }
  1532. /* current hash */
  1533. struct aws_byte_cursor current_chunk_hash_cursor = aws_byte_cursor_from_buf(&state->payload_hash);
  1534. if (aws_byte_buf_append_dynamic(dest, &current_chunk_hash_cursor)) {
  1535. return AWS_OP_ERR;
  1536. }
  1537. return AWS_OP_SUCCESS;
  1538. }
  1539. static int s_build_canonical_request_trailing_headers(struct aws_signing_state_aws *state) {
  1540. struct aws_byte_buf *dest = &state->string_to_sign_payload;
  1541. /* previous signature + \n */
  1542. struct aws_byte_cursor prev_signature_cursor;
  1543. AWS_ZERO_STRUCT(prev_signature_cursor);
  1544. if (aws_signable_get_property(state->signable, g_aws_previous_signature_property_name, &prev_signature_cursor)) {
  1545. AWS_LOGF_ERROR(
  1546. AWS_LS_AUTH_SIGNING,
  1547. "(id=%p) trailing_headers signable missing previous signature property",
  1548. (void *)state->signable);
  1549. return aws_raise_error(AWS_AUTH_SIGNING_MISSING_PREVIOUS_SIGNATURE);
  1550. }
  1551. /* strip any padding (AWS_SIGV4A_SIGNATURE_PADDING_BYTE) from the previous signature */
  1552. prev_signature_cursor = aws_trim_padded_sigv4a_signature(prev_signature_cursor);
  1553. if (aws_byte_buf_append_dynamic(dest, &prev_signature_cursor)) {
  1554. return AWS_OP_ERR;
  1555. }
  1556. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1557. return AWS_OP_ERR;
  1558. }
  1559. /* current hash */
  1560. if (s_canonicalize_headers(state)) {
  1561. return AWS_OP_ERR;
  1562. }
  1563. struct aws_byte_cursor header_block_cursor = aws_byte_cursor_from_buf(&state->canonical_header_block);
  1564. if (aws_byte_buf_append_dynamic(&state->canonical_request, &header_block_cursor)) {
  1565. return AWS_OP_ERR;
  1566. }
  1567. if (s_build_canonical_request_hash(state)) {
  1568. return AWS_OP_ERR;
  1569. }
  1570. return AWS_OP_SUCCESS;
  1571. }
  1572. /*
  1573. * Builds a sigv4-signed canonical request and its hashed value
  1574. */
  1575. static int s_build_canonical_request_sigv4(struct aws_signing_state_aws *state) {
  1576. AWS_ASSERT(state->canonical_request.len == 0);
  1577. AWS_ASSERT(state->payload_hash.len > 0);
  1578. int result = AWS_OP_ERR;
  1579. struct aws_uri uri;
  1580. AWS_ZERO_STRUCT(uri);
  1581. struct aws_byte_cursor uri_cursor;
  1582. if (aws_signable_get_property(state->signable, g_aws_http_uri_property_name, &uri_cursor)) {
  1583. return AWS_OP_ERR;
  1584. }
  1585. if (aws_uri_init_parse(&uri, state->allocator, &uri_cursor)) {
  1586. goto cleanup;
  1587. }
  1588. if (s_build_canonical_headers(state)) {
  1589. goto cleanup;
  1590. }
  1591. if (s_append_canonical_method(state)) {
  1592. goto cleanup;
  1593. }
  1594. if (s_append_canonical_path(&uri, state)) {
  1595. goto cleanup;
  1596. }
  1597. if (s_append_canonical_query_string(&uri, state)) {
  1598. goto cleanup;
  1599. }
  1600. struct aws_byte_cursor header_block_cursor = aws_byte_cursor_from_buf(&state->canonical_header_block);
  1601. if (aws_byte_buf_append_dynamic(&state->canonical_request, &header_block_cursor)) {
  1602. goto cleanup;
  1603. }
  1604. if (s_append_canonical_payload_hash(state)) {
  1605. goto cleanup;
  1606. }
  1607. if (s_build_canonical_request_hash(state)) {
  1608. goto cleanup;
  1609. }
  1610. result = AWS_OP_SUCCESS;
  1611. cleanup:
  1612. aws_uri_clean_up(&uri);
  1613. return result;
  1614. }
  1615. /*
  1616. * The canonical header list is the next-to-the-last line on the canonical request, so split by lines and take
  1617. * the penultimate value.
  1618. */
  1619. static struct aws_byte_cursor s_get_signed_headers_from_canonical_request(
  1620. struct aws_allocator *allocator,
  1621. struct aws_byte_cursor canonical_request) {
  1622. struct aws_byte_cursor header_cursor;
  1623. AWS_ZERO_STRUCT(header_cursor);
  1624. struct aws_array_list splits;
  1625. AWS_ZERO_STRUCT(splits);
  1626. if (aws_array_list_init_dynamic(
  1627. &splits, allocator, CANONICAL_REQUEST_SPLIT_OVER_ESTIMATE, sizeof(struct aws_byte_cursor))) {
  1628. return header_cursor;
  1629. }
  1630. if (aws_byte_cursor_split_on_char(&canonical_request, '\n', &splits)) {
  1631. goto done;
  1632. }
  1633. size_t split_count = aws_array_list_length(&splits);
  1634. if (split_count > 1) {
  1635. aws_array_list_get_at(&splits, &header_cursor, split_count - 2);
  1636. }
  1637. done:
  1638. aws_array_list_clean_up(&splits);
  1639. return header_cursor;
  1640. }
  1641. /*
  1642. * Fill in the signing state values needed by later stages that computing the canonical request would have done.
  1643. */
  1644. static int s_apply_existing_canonical_request(struct aws_signing_state_aws *state) {
  1645. struct aws_byte_cursor canonical_request_cursor;
  1646. AWS_ZERO_STRUCT(canonical_request_cursor);
  1647. if (aws_signable_get_property(state->signable, g_aws_canonical_request_property_name, &canonical_request_cursor)) {
  1648. return AWS_OP_ERR;
  1649. }
  1650. if (aws_byte_buf_append_dynamic(&state->canonical_request, &canonical_request_cursor)) {
  1651. return AWS_OP_ERR;
  1652. }
  1653. struct aws_byte_cursor signed_headers_cursor =
  1654. s_get_signed_headers_from_canonical_request(state->allocator, canonical_request_cursor);
  1655. if (aws_byte_buf_append_dynamic(&state->signed_headers, &signed_headers_cursor)) {
  1656. return AWS_OP_ERR;
  1657. }
  1658. if (s_build_canonical_request_hash(state)) {
  1659. return AWS_OP_ERR;
  1660. }
  1661. return AWS_OP_SUCCESS;
  1662. }
  1663. /*
  1664. * Top-level canonical request construction function.
  1665. * For signature types not associated directly with an http request (chunks, events), this calculates the
  1666. * string-to-sign payload that replaces the hashed canonical request in those signing procedures.
  1667. */
  1668. int aws_signing_build_canonical_request(struct aws_signing_state_aws *state) {
  1669. if (aws_date_time_to_utc_time_str(&state->config.date, AWS_DATE_FORMAT_ISO_8601_BASIC, &state->date)) {
  1670. return AWS_OP_ERR;
  1671. }
  1672. if (s_build_canonical_payload(state)) {
  1673. return AWS_OP_ERR;
  1674. }
  1675. if (s_build_credential_scope(state)) {
  1676. return AWS_OP_ERR;
  1677. }
  1678. switch (state->config.signature_type) {
  1679. case AWS_ST_HTTP_REQUEST_HEADERS:
  1680. case AWS_ST_HTTP_REQUEST_QUERY_PARAMS:
  1681. return s_build_canonical_request_sigv4(state);
  1682. case AWS_ST_HTTP_REQUEST_CHUNK:
  1683. return s_build_canonical_request_body_chunk(state);
  1684. case AWS_ST_HTTP_REQUEST_EVENT:
  1685. return s_build_string_to_sign_payload_for_event(state);
  1686. case AWS_ST_HTTP_REQUEST_TRAILING_HEADERS:
  1687. return s_build_canonical_request_trailing_headers(state);
  1688. case AWS_ST_CANONICAL_REQUEST_HEADERS:
  1689. case AWS_ST_CANONICAL_REQUEST_QUERY_PARAMS:
  1690. return s_apply_existing_canonical_request(state);
  1691. default:
  1692. return AWS_OP_ERR;
  1693. }
  1694. }
  1695. /*
  1696. * Top-level function for computing the string-to-sign in an AWS signing process.
  1697. */
  1698. int aws_signing_build_string_to_sign(struct aws_signing_state_aws *state) {
  1699. /* We must have a canonical request and the credential scope. We must not have the string to sign */
  1700. AWS_ASSERT(state->string_to_sign_payload.len > 0);
  1701. AWS_ASSERT(state->credential_scope.len > 0);
  1702. AWS_ASSERT(state->string_to_sign.len == 0);
  1703. struct aws_byte_buf *dest = &state->string_to_sign;
  1704. if (s_append_sts_signature_type(state, dest)) {
  1705. return AWS_OP_ERR;
  1706. }
  1707. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1708. return AWS_OP_ERR;
  1709. }
  1710. /* date_time output uses raw array writes, so ensure there's enough room beforehand */
  1711. if (aws_byte_buf_reserve_relative(dest, AWS_DATE_TIME_STR_MAX_LEN)) {
  1712. return AWS_OP_ERR;
  1713. }
  1714. struct aws_byte_cursor date_cursor = aws_byte_cursor_from_buf(&state->date);
  1715. if (aws_byte_buf_append_dynamic(dest, &date_cursor)) {
  1716. return AWS_OP_ERR;
  1717. }
  1718. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1719. return AWS_OP_ERR;
  1720. }
  1721. struct aws_byte_cursor credential_scope_cursor = aws_byte_cursor_from_buf(&state->credential_scope);
  1722. if (aws_byte_buf_append_dynamic(dest, &credential_scope_cursor)) {
  1723. return AWS_OP_ERR;
  1724. }
  1725. if (aws_byte_buf_append_byte_dynamic(dest, '\n')) {
  1726. return AWS_OP_ERR;
  1727. }
  1728. struct aws_byte_cursor sts_payload_cursor = aws_byte_cursor_from_buf(&state->string_to_sign_payload);
  1729. if (aws_byte_buf_append_dynamic(dest, &sts_payload_cursor)) {
  1730. return AWS_OP_ERR;
  1731. }
  1732. return AWS_OP_SUCCESS;
  1733. }
  1734. /*
  1735. * Signature calculation utility functions
  1736. */
  1737. AWS_STATIC_STRING_FROM_LITERAL(s_secret_key_prefix, "AWS4");
  1738. /*
  1739. * Computes the key to sign with as a function of the secret access key in the credentials and
  1740. * the components of the credential scope: date, region, service, algorithm terminator
  1741. */
  1742. static int s_compute_sigv4_signing_key(struct aws_signing_state_aws *state, struct aws_byte_buf *dest) {
  1743. /* dest should be empty */
  1744. AWS_ASSERT(dest->len == 0);
  1745. const struct aws_signing_config_aws *config = &state->config;
  1746. struct aws_allocator *allocator = state->allocator;
  1747. int result = AWS_OP_ERR;
  1748. struct aws_byte_buf secret_key;
  1749. AWS_ZERO_STRUCT(secret_key);
  1750. struct aws_byte_buf output;
  1751. AWS_ZERO_STRUCT(output);
  1752. struct aws_byte_buf date_buf;
  1753. AWS_ZERO_STRUCT(date_buf);
  1754. struct aws_byte_cursor secret_access_key_cursor = aws_credentials_get_secret_access_key(state->config.credentials);
  1755. if (aws_byte_buf_init(&secret_key, allocator, s_secret_key_prefix->len + secret_access_key_cursor.len) ||
  1756. aws_byte_buf_init(&output, allocator, AWS_SHA256_LEN) ||
  1757. aws_byte_buf_init(&date_buf, allocator, AWS_DATE_TIME_STR_MAX_LEN)) {
  1758. goto cleanup;
  1759. }
  1760. /*
  1761. * Prep Key
  1762. */
  1763. struct aws_byte_cursor prefix_cursor = aws_byte_cursor_from_string(s_secret_key_prefix);
  1764. if (aws_byte_buf_append_dynamic(&secret_key, &prefix_cursor) ||
  1765. aws_byte_buf_append_dynamic(&secret_key, &secret_access_key_cursor)) {
  1766. goto cleanup;
  1767. }
  1768. /*
  1769. * Prep date
  1770. */
  1771. if (aws_date_time_to_utc_time_short_str(&config->date, AWS_DATE_FORMAT_ISO_8601_BASIC, &date_buf)) {
  1772. goto cleanup;
  1773. }
  1774. struct aws_byte_cursor date_cursor = aws_byte_cursor_from_buf(&date_buf);
  1775. struct aws_byte_cursor secret_key_cursor = aws_byte_cursor_from_buf(&secret_key);
  1776. if (aws_sha256_hmac_compute(allocator, &secret_key_cursor, &date_cursor, &output, 0)) {
  1777. goto cleanup;
  1778. }
  1779. struct aws_byte_cursor chained_key_cursor = aws_byte_cursor_from_buf(&output);
  1780. output.len = 0; /* necessary evil part 1*/
  1781. if (aws_sha256_hmac_compute(allocator, &chained_key_cursor, &config->region, &output, 0)) {
  1782. goto cleanup;
  1783. }
  1784. chained_key_cursor = aws_byte_cursor_from_buf(&output);
  1785. output.len = 0; /* necessary evil part 2 */
  1786. if (aws_sha256_hmac_compute(allocator, &chained_key_cursor, &config->service, &output, 0)) {
  1787. goto cleanup;
  1788. }
  1789. chained_key_cursor = aws_byte_cursor_from_buf(&output);
  1790. struct aws_byte_cursor scope_terminator_cursor = aws_byte_cursor_from_string(s_credential_scope_sigv4_terminator);
  1791. if (aws_sha256_hmac_compute(allocator, &chained_key_cursor, &scope_terminator_cursor, dest, 0)) {
  1792. goto cleanup;
  1793. }
  1794. result = AWS_OP_SUCCESS;
  1795. cleanup:
  1796. aws_byte_buf_clean_up_secure(&secret_key);
  1797. aws_byte_buf_clean_up(&output);
  1798. aws_byte_buf_clean_up(&date_buf);
  1799. return result;
  1800. }
  1801. /*
  1802. * Calculates the hex-encoding of the final signature value from the sigv4 signing process
  1803. */
  1804. static int s_calculate_sigv4_signature_value(struct aws_signing_state_aws *state) {
  1805. struct aws_allocator *allocator = state->allocator;
  1806. int result = AWS_OP_ERR;
  1807. struct aws_byte_buf key;
  1808. AWS_ZERO_STRUCT(key);
  1809. struct aws_byte_buf digest;
  1810. AWS_ZERO_STRUCT(digest);
  1811. if (aws_byte_buf_init(&key, allocator, AWS_SHA256_LEN) || aws_byte_buf_init(&digest, allocator, AWS_SHA256_LEN)) {
  1812. goto cleanup;
  1813. }
  1814. if (s_compute_sigv4_signing_key(state, &key)) {
  1815. goto cleanup;
  1816. }
  1817. struct aws_byte_cursor key_cursor = aws_byte_cursor_from_buf(&key);
  1818. struct aws_byte_cursor string_to_sign_cursor = aws_byte_cursor_from_buf(&state->string_to_sign);
  1819. if (aws_sha256_hmac_compute(allocator, &key_cursor, &string_to_sign_cursor, &digest, 0)) {
  1820. goto cleanup;
  1821. }
  1822. struct aws_byte_cursor digest_cursor = aws_byte_cursor_from_buf(&digest);
  1823. if (aws_hex_encode_append_dynamic(&digest_cursor, &state->signature)) {
  1824. goto cleanup;
  1825. }
  1826. result = AWS_OP_SUCCESS;
  1827. cleanup:
  1828. aws_byte_buf_clean_up(&key);
  1829. aws_byte_buf_clean_up(&digest);
  1830. return result;
  1831. }
  1832. /*
  1833. * Calculates the hex-encoding of the final signature value from the sigv4a signing process
  1834. */
  1835. static int s_calculate_sigv4a_signature_value(struct aws_signing_state_aws *state) {
  1836. struct aws_allocator *allocator = state->allocator;
  1837. int result = AWS_OP_ERR;
  1838. struct aws_byte_buf ecdsa_digest;
  1839. AWS_ZERO_STRUCT(ecdsa_digest);
  1840. struct aws_byte_buf sha256_digest;
  1841. AWS_ZERO_STRUCT(sha256_digest);
  1842. struct aws_ecc_key_pair *ecc_key = aws_credentials_get_ecc_key_pair(state->config.credentials);
  1843. if (ecc_key == NULL) {
  1844. return aws_raise_error(AWS_AUTH_SIGNING_INVALID_CREDENTIALS);
  1845. }
  1846. if (aws_byte_buf_init(&ecdsa_digest, allocator, aws_ecc_key_pair_signature_length(ecc_key)) ||
  1847. aws_byte_buf_init(&sha256_digest, allocator, AWS_SHA256_LEN)) {
  1848. goto cleanup;
  1849. }
  1850. struct aws_byte_cursor string_to_sign_cursor = aws_byte_cursor_from_buf(&state->string_to_sign);
  1851. if (aws_sha256_compute(allocator, &string_to_sign_cursor, &sha256_digest, 0)) {
  1852. goto cleanup;
  1853. }
  1854. struct aws_byte_cursor sha256_digest_cursor = aws_byte_cursor_from_buf(&sha256_digest);
  1855. if (aws_ecc_key_pair_sign_message(ecc_key, &sha256_digest_cursor, &ecdsa_digest)) {
  1856. goto cleanup;
  1857. }
  1858. struct aws_byte_cursor ecdsa_digest_cursor = aws_byte_cursor_from_buf(&ecdsa_digest);
  1859. if (aws_hex_encode_append_dynamic(&ecdsa_digest_cursor, &state->signature)) {
  1860. goto cleanup;
  1861. }
  1862. result = AWS_OP_SUCCESS;
  1863. cleanup:
  1864. aws_byte_buf_clean_up(&ecdsa_digest);
  1865. aws_byte_buf_clean_up(&sha256_digest);
  1866. return result;
  1867. }
  1868. /*
  1869. * Appends a final signature value to a buffer based on the requested signing algorithm
  1870. */
  1871. int s_calculate_signature_value(struct aws_signing_state_aws *state) {
  1872. switch (state->config.algorithm) {
  1873. case AWS_SIGNING_ALGORITHM_V4:
  1874. return s_calculate_sigv4_signature_value(state);
  1875. case AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC:
  1876. return s_calculate_sigv4a_signature_value(state);
  1877. default:
  1878. return aws_raise_error(AWS_AUTH_SIGNING_UNSUPPORTED_ALGORITHM);
  1879. }
  1880. }
  1881. static int s_add_signature_property_to_result_set(struct aws_signing_state_aws *state) {
  1882. int result = AWS_OP_ERR;
  1883. struct aws_byte_buf final_signature_buffer;
  1884. AWS_ZERO_STRUCT(final_signature_buffer);
  1885. if (aws_byte_buf_init(&final_signature_buffer, state->allocator, HEX_ENCODED_SIGNATURE_OVER_ESTIMATE)) {
  1886. return AWS_OP_ERR;
  1887. }
  1888. struct aws_byte_cursor signature_value = aws_byte_cursor_from_buf(&state->signature);
  1889. if (aws_byte_buf_append_dynamic(&final_signature_buffer, &signature_value)) {
  1890. goto cleanup;
  1891. }
  1892. if (state->config.algorithm == AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC &&
  1893. (state->config.signature_type == AWS_ST_HTTP_REQUEST_CHUNK ||
  1894. state->config.signature_type == AWS_ST_HTTP_REQUEST_TRAILING_HEADERS)) {
  1895. if (aws_byte_buf_reserve(&final_signature_buffer, MAX_ECDSA_P256_SIGNATURE_AS_HEX_LENGTH)) {
  1896. goto cleanup;
  1897. }
  1898. if (signature_value.len < MAX_ECDSA_P256_SIGNATURE_AS_HEX_LENGTH) {
  1899. size_t padding_byte_count = MAX_ECDSA_P256_SIGNATURE_AS_HEX_LENGTH - signature_value.len;
  1900. if (!aws_byte_buf_write_u8_n(
  1901. &final_signature_buffer, AWS_SIGV4A_SIGNATURE_PADDING_BYTE, padding_byte_count)) {
  1902. goto cleanup;
  1903. }
  1904. }
  1905. }
  1906. signature_value = aws_byte_cursor_from_buf(&final_signature_buffer);
  1907. if (aws_signing_result_set_property(&state->result, g_aws_signature_property_name, &signature_value)) {
  1908. return AWS_OP_ERR;
  1909. }
  1910. result = AWS_OP_SUCCESS;
  1911. cleanup:
  1912. aws_byte_buf_clean_up(&final_signature_buffer);
  1913. return result;
  1914. }
  1915. /*
  1916. * Adds the appropriate authorization header or query param to the signing result
  1917. */
  1918. static int s_add_authorization_to_result(
  1919. struct aws_signing_state_aws *state,
  1920. struct aws_byte_buf *authorization_value) {
  1921. struct aws_byte_cursor name;
  1922. struct aws_byte_cursor value = aws_byte_cursor_from_buf(authorization_value);
  1923. if (s_is_header_based_signature_value(state->config.signature_type)) {
  1924. name = aws_byte_cursor_from_string(g_aws_signing_authorization_header_name);
  1925. if (aws_signing_result_append_property_list(
  1926. &state->result, g_aws_http_headers_property_list_name, &name, &value)) {
  1927. return AWS_OP_ERR;
  1928. }
  1929. }
  1930. if (s_is_query_param_based_signature_value(state->config.signature_type)) {
  1931. name = aws_byte_cursor_from_string(g_aws_signing_authorization_query_param_name);
  1932. if (aws_signing_result_append_property_list(
  1933. &state->result, g_aws_http_query_params_property_list_name, &name, &value)) {
  1934. return AWS_OP_ERR;
  1935. }
  1936. }
  1937. /*
  1938. * Unconditionally add the signature value as a top-level property.
  1939. */
  1940. if (s_add_signature_property_to_result_set(state)) {
  1941. return AWS_OP_ERR;
  1942. }
  1943. return AWS_OP_SUCCESS;
  1944. }
  1945. AWS_STATIC_STRING_FROM_LITERAL(s_credential_prefix, " Credential=");
  1946. AWS_STATIC_STRING_FROM_LITERAL(s_signed_headers_prefix, ", SignedHeaders=");
  1947. AWS_STATIC_STRING_FROM_LITERAL(s_signature_prefix, ", Signature=");
  1948. /*
  1949. * The Authorization has a lot more than just the final signature value in it. This function appends all those
  1950. * other values together ala:
  1951. *
  1952. * "AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/service/aws4_request, SignedHeaders=host;x-amz-date,
  1953. * Signature="
  1954. *
  1955. * The final header value is this with the signature value appended to the end.
  1956. */
  1957. static int s_append_authorization_header_preamble(struct aws_signing_state_aws *state, struct aws_byte_buf *dest) {
  1958. if (s_append_sts_signature_type(state, dest)) {
  1959. return AWS_OP_ERR;
  1960. }
  1961. struct aws_byte_cursor credential_cursor = aws_byte_cursor_from_string(s_credential_prefix);
  1962. if (aws_byte_buf_append_dynamic(dest, &credential_cursor)) {
  1963. return AWS_OP_ERR;
  1964. }
  1965. struct aws_byte_cursor access_key_cursor = aws_credentials_get_access_key_id(state->config.credentials);
  1966. if (aws_byte_buf_append_dynamic(dest, &access_key_cursor)) {
  1967. return AWS_OP_ERR;
  1968. }
  1969. if (aws_byte_buf_append_byte_dynamic(dest, '/')) {
  1970. return AWS_OP_ERR;
  1971. }
  1972. struct aws_byte_cursor credential_scope_cursor = aws_byte_cursor_from_buf(&state->credential_scope);
  1973. if (aws_byte_buf_append_dynamic(dest, &credential_scope_cursor)) {
  1974. return AWS_OP_ERR;
  1975. }
  1976. struct aws_byte_cursor signed_headers_prefix_cursor = aws_byte_cursor_from_string(s_signed_headers_prefix);
  1977. if (aws_byte_buf_append_dynamic(dest, &signed_headers_prefix_cursor)) {
  1978. return AWS_OP_ERR;
  1979. }
  1980. struct aws_byte_cursor signed_headers_cursor = aws_byte_cursor_from_buf(&state->signed_headers);
  1981. if (aws_byte_buf_append_dynamic(dest, &signed_headers_cursor)) {
  1982. return AWS_OP_ERR;
  1983. }
  1984. struct aws_byte_cursor signature_prefix_cursor = aws_byte_cursor_from_string(s_signature_prefix);
  1985. if (aws_byte_buf_append_dynamic(dest, &signature_prefix_cursor)) {
  1986. return AWS_OP_ERR;
  1987. }
  1988. return AWS_OP_SUCCESS;
  1989. }
  1990. /*
  1991. * Top-level function for constructing the final authorization header/query-param and adding it to the
  1992. * signing result.
  1993. */
  1994. int aws_signing_build_authorization_value(struct aws_signing_state_aws *state) {
  1995. AWS_ASSERT(state->string_to_sign.len > 0);
  1996. AWS_ASSERT(state->credential_scope.len > 0);
  1997. int result = AWS_OP_ERR;
  1998. struct aws_byte_buf authorization_value;
  1999. if (aws_byte_buf_init(&authorization_value, state->allocator, AUTHORIZATION_VALUE_STARTING_SIZE)) {
  2000. goto cleanup;
  2001. }
  2002. if (s_is_header_based_signature_value(state->config.signature_type) &&
  2003. s_append_authorization_header_preamble(state, &authorization_value)) {
  2004. goto cleanup;
  2005. }
  2006. if (s_calculate_signature_value(state)) {
  2007. goto cleanup;
  2008. }
  2009. struct aws_byte_cursor signature_cursor = aws_byte_cursor_from_buf(&state->signature);
  2010. if (aws_byte_buf_append_dynamic(&authorization_value, &signature_cursor)) {
  2011. goto cleanup;
  2012. }
  2013. if (s_add_authorization_to_result(state, &authorization_value)) {
  2014. goto cleanup;
  2015. }
  2016. AWS_LOGF_INFO(
  2017. AWS_LS_AUTH_SIGNING,
  2018. "(id=%p) Http request successfully built final authorization value via algorithm %s, with contents "
  2019. "\n" PRInSTR "\n",
  2020. (void *)state->signable,
  2021. aws_signing_algorithm_to_string(state->config.algorithm),
  2022. AWS_BYTE_BUF_PRI(authorization_value));
  2023. result = AWS_OP_SUCCESS;
  2024. cleanup:
  2025. aws_byte_buf_clean_up(&authorization_value);
  2026. return result;
  2027. }
  2028. int aws_validate_v4a_authorization_value(
  2029. struct aws_allocator *allocator,
  2030. struct aws_ecc_key_pair *ecc_key,
  2031. struct aws_byte_cursor string_to_sign_cursor,
  2032. struct aws_byte_cursor signature_value_cursor) {
  2033. AWS_LOGF_DEBUG(
  2034. AWS_LS_AUTH_SIGNING,
  2035. "(id=%p) Verifying v4a auth value: \n" PRInSTR "\n\nusing string-to-sign: \n" PRInSTR "\n\n",
  2036. (void *)ecc_key,
  2037. AWS_BYTE_CURSOR_PRI(signature_value_cursor),
  2038. AWS_BYTE_CURSOR_PRI(string_to_sign_cursor));
  2039. signature_value_cursor = aws_trim_padded_sigv4a_signature(signature_value_cursor);
  2040. size_t binary_length = 0;
  2041. if (aws_hex_compute_decoded_len(signature_value_cursor.len, &binary_length)) {
  2042. return AWS_OP_ERR;
  2043. }
  2044. int result = AWS_OP_ERR;
  2045. struct aws_byte_buf binary_signature;
  2046. AWS_ZERO_STRUCT(binary_signature);
  2047. struct aws_byte_buf sha256_digest;
  2048. AWS_ZERO_STRUCT(sha256_digest);
  2049. if (aws_byte_buf_init(&binary_signature, allocator, binary_length) ||
  2050. aws_byte_buf_init(&sha256_digest, allocator, AWS_SHA256_LEN)) {
  2051. goto done;
  2052. }
  2053. if (aws_hex_decode(&signature_value_cursor, &binary_signature)) {
  2054. goto done;
  2055. }
  2056. if (aws_sha256_compute(allocator, &string_to_sign_cursor, &sha256_digest, 0)) {
  2057. goto done;
  2058. }
  2059. struct aws_byte_cursor binary_signature_cursor =
  2060. aws_byte_cursor_from_array(binary_signature.buffer, binary_signature.len);
  2061. struct aws_byte_cursor digest_cursor = aws_byte_cursor_from_buf(&sha256_digest);
  2062. if (aws_ecc_key_pair_verify_signature(ecc_key, &digest_cursor, &binary_signature_cursor)) {
  2063. goto done;
  2064. }
  2065. result = AWS_OP_SUCCESS;
  2066. done:
  2067. aws_byte_buf_clean_up(&binary_signature);
  2068. aws_byte_buf_clean_up(&sha256_digest);
  2069. return result;
  2070. }
  2071. int aws_verify_sigv4a_signing(
  2072. struct aws_allocator *allocator,
  2073. const struct aws_signable *signable,
  2074. const struct aws_signing_config_base *base_config,
  2075. struct aws_byte_cursor expected_canonical_request_cursor,
  2076. struct aws_byte_cursor signature_cursor,
  2077. struct aws_byte_cursor ecc_key_pub_x,
  2078. struct aws_byte_cursor ecc_key_pub_y) {
  2079. int result = AWS_OP_ERR;
  2080. if (base_config->config_type != AWS_SIGNING_CONFIG_AWS) {
  2081. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Signing config is not an AWS signing config");
  2082. return aws_raise_error(AWS_AUTH_SIGNING_MISMATCHED_CONFIGURATION);
  2083. }
  2084. if (aws_validate_aws_signing_config_aws((void *)base_config)) {
  2085. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Signing config failed validation");
  2086. return aws_raise_error(AWS_AUTH_SIGNING_INVALID_CONFIGURATION);
  2087. }
  2088. const struct aws_signing_config_aws *config = (void *)base_config;
  2089. if (config->algorithm != AWS_SIGNING_ALGORITHM_V4_ASYMMETRIC) {
  2090. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Signing algorithm is not V4_ASYMMETRIC");
  2091. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  2092. }
  2093. if (config->credentials == NULL) {
  2094. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "AWS credentials were not provided/null");
  2095. return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  2096. }
  2097. struct aws_signing_state_aws *signing_state = aws_signing_state_new(allocator, config, signable, NULL, NULL);
  2098. if (!signing_state) {
  2099. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Unable to create new signing state");
  2100. return AWS_OP_ERR;
  2101. }
  2102. AWS_LOGF_DEBUG(
  2103. AWS_LS_AUTH_SIGNING,
  2104. "(id=%p) Verifying v4a signature: \n" PRInSTR "\n\nagainst expected canonical request: \n" PRInSTR
  2105. "\n\nusing ecc key:\n X:" PRInSTR "\n Y:" PRInSTR "\n\n",
  2106. (void *)signable,
  2107. AWS_BYTE_CURSOR_PRI(signature_cursor),
  2108. AWS_BYTE_CURSOR_PRI(expected_canonical_request_cursor),
  2109. AWS_BYTE_CURSOR_PRI(ecc_key_pub_x),
  2110. AWS_BYTE_CURSOR_PRI(ecc_key_pub_y));
  2111. struct aws_ecc_key_pair *verification_key =
  2112. aws_ecc_key_new_from_hex_coordinates(allocator, AWS_CAL_ECDSA_P256, ecc_key_pub_x, ecc_key_pub_y);
  2113. if (verification_key == NULL) {
  2114. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Unable to create an ECC key from provided coordinates");
  2115. goto done;
  2116. }
  2117. if (aws_credentials_get_ecc_key_pair(signing_state->config.credentials) == NULL) {
  2118. struct aws_credentials *ecc_credentials =
  2119. aws_credentials_new_ecc_from_aws_credentials(allocator, signing_state->config.credentials);
  2120. aws_credentials_release(signing_state->config.credentials);
  2121. signing_state->config.credentials = ecc_credentials;
  2122. if (signing_state->config.credentials == NULL) {
  2123. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Unable to create ECC from provided credentials");
  2124. goto done;
  2125. }
  2126. }
  2127. if (aws_signing_build_canonical_request(signing_state)) {
  2128. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Unable to canonicalize request for signing");
  2129. goto done;
  2130. }
  2131. struct aws_byte_cursor canonical_request_cursor = aws_byte_cursor_from_buf(&signing_state->canonical_request);
  2132. if (aws_byte_cursor_compare_lexical(&expected_canonical_request_cursor, &canonical_request_cursor) != 0) {
  2133. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Canonicalized request and expected canonical request do not match");
  2134. aws_raise_error(AWS_AUTH_CANONICAL_REQUEST_MISMATCH);
  2135. goto done;
  2136. }
  2137. if (aws_signing_build_string_to_sign(signing_state)) {
  2138. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Unable to build string to sign from canonical request");
  2139. goto done;
  2140. }
  2141. if (aws_validate_v4a_authorization_value(
  2142. allocator, verification_key, aws_byte_cursor_from_buf(&signing_state->string_to_sign), signature_cursor)) {
  2143. AWS_LOGF_ERROR(AWS_LS_AUTH_SIGNING, "Signature does not validate");
  2144. aws_raise_error(AWS_AUTH_SIGV4A_SIGNATURE_VALIDATION_FAILURE);
  2145. goto done;
  2146. }
  2147. result = AWS_OP_SUCCESS;
  2148. done:
  2149. if (verification_key) {
  2150. aws_ecc_key_pair_release(verification_key);
  2151. }
  2152. aws_signing_state_destroy(signing_state);
  2153. return result;
  2154. }
  2155. static bool s_is_padding_byte(uint8_t byte) {
  2156. return byte == AWS_SIGV4A_SIGNATURE_PADDING_BYTE;
  2157. }
  2158. struct aws_byte_cursor aws_trim_padded_sigv4a_signature(struct aws_byte_cursor signature) {
  2159. return aws_byte_cursor_trim_pred(&signature, s_is_padding_byte);
  2160. }