xref: /aosp_15_r20/external/libwebsockets/lib/secure-streams/system/auth-sigv4/sign.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * Sigv4 support for Secure Streams
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2020 Andy Green <[email protected]>
7*1c60b9acSAndroid Build Coastguard Worker  *                    [email protected]
8*1c60b9acSAndroid Build Coastguard Worker  *
9*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
10*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
11*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
12*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
14*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
17*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
18*1c60b9acSAndroid Build Coastguard Worker  *
19*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
26*1c60b9acSAndroid Build Coastguard Worker  */
27*1c60b9acSAndroid Build Coastguard Worker 
28*1c60b9acSAndroid Build Coastguard Worker #include <private-lib-core.h>
29*1c60b9acSAndroid Build Coastguard Worker 
30*1c60b9acSAndroid Build Coastguard Worker struct sigv4_header {
31*1c60b9acSAndroid Build Coastguard Worker 	const char * name;
32*1c60b9acSAndroid Build Coastguard Worker 	const char * value;
33*1c60b9acSAndroid Build Coastguard Worker };
34*1c60b9acSAndroid Build Coastguard Worker 
35*1c60b9acSAndroid Build Coastguard Worker #define MAX_HEADER_NUM 8
36*1c60b9acSAndroid Build Coastguard Worker struct sigv4 {
37*1c60b9acSAndroid Build Coastguard Worker 	struct sigv4_header headers[MAX_HEADER_NUM];
38*1c60b9acSAndroid Build Coastguard Worker 	uint8_t	hnum;
39*1c60b9acSAndroid Build Coastguard Worker 	char	ymd[10];     /*YYYYMMDD*/
40*1c60b9acSAndroid Build Coastguard Worker 	const char *timestamp;
41*1c60b9acSAndroid Build Coastguard Worker 	const char *payload_hash;
42*1c60b9acSAndroid Build Coastguard Worker 	const char *region;
43*1c60b9acSAndroid Build Coastguard Worker 	const char *service;
44*1c60b9acSAndroid Build Coastguard Worker };
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker static const uint8_t blob_idx[] = {
47*1c60b9acSAndroid Build Coastguard Worker 	LWS_SYSBLOB_TYPE_EXT_AUTH1,
48*1c60b9acSAndroid Build Coastguard Worker 	LWS_SYSBLOB_TYPE_EXT_AUTH2,
49*1c60b9acSAndroid Build Coastguard Worker 	LWS_SYSBLOB_TYPE_EXT_AUTH3,
50*1c60b9acSAndroid Build Coastguard Worker 	LWS_SYSBLOB_TYPE_EXT_AUTH4,
51*1c60b9acSAndroid Build Coastguard Worker };
52*1c60b9acSAndroid Build Coastguard Worker 
53*1c60b9acSAndroid Build Coastguard Worker enum {
54*1c60b9acSAndroid Build Coastguard Worker 	LWS_SS_SIGV4_KEYID,
55*1c60b9acSAndroid Build Coastguard Worker 	LWS_SS_SIGV4_KEY,
56*1c60b9acSAndroid Build Coastguard Worker 	LWS_SS_SIGV4_BLOB_SLOTS
57*1c60b9acSAndroid Build Coastguard Worker };
58*1c60b9acSAndroid Build Coastguard Worker 
add_header(struct sigv4 * s,const char * name,const char * value)59*1c60b9acSAndroid Build Coastguard Worker static inline int add_header(struct sigv4 *s, const char *name, const char *value)
60*1c60b9acSAndroid Build Coastguard Worker {
61*1c60b9acSAndroid Build Coastguard Worker 	if (s->hnum >= MAX_HEADER_NUM) {
62*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s too many sigv4 headers\n", __func__);
63*1c60b9acSAndroid Build Coastguard Worker 		return -1;
64*1c60b9acSAndroid Build Coastguard Worker 	}
65*1c60b9acSAndroid Build Coastguard Worker 
66*1c60b9acSAndroid Build Coastguard Worker 	s->headers[s->hnum].name = name;
67*1c60b9acSAndroid Build Coastguard Worker 	s->headers[s->hnum].value = value;
68*1c60b9acSAndroid Build Coastguard Worker 	s->hnum++;
69*1c60b9acSAndroid Build Coastguard Worker 
70*1c60b9acSAndroid Build Coastguard Worker 	if (!strncmp(name, "x-amz-content-sha256", strlen("x-amz-content-sha256")))
71*1c60b9acSAndroid Build Coastguard Worker 		s->payload_hash = value;
72*1c60b9acSAndroid Build Coastguard Worker 
73*1c60b9acSAndroid Build Coastguard Worker 	if (!strncmp(name, "x-amz-date", strlen("x-amz-date"))) {
74*1c60b9acSAndroid Build Coastguard Worker 		s->timestamp = value;
75*1c60b9acSAndroid Build Coastguard Worker 		strncpy(s->ymd, value, 8);
76*1c60b9acSAndroid Build Coastguard Worker 	}
77*1c60b9acSAndroid Build Coastguard Worker 
78*1c60b9acSAndroid Build Coastguard Worker 	return 0;
79*1c60b9acSAndroid Build Coastguard Worker }
80*1c60b9acSAndroid Build Coastguard Worker 
81*1c60b9acSAndroid Build Coastguard Worker static int
cmp_header(const void * a,const void * b)82*1c60b9acSAndroid Build Coastguard Worker cmp_header(const void * a, const void * b)
83*1c60b9acSAndroid Build Coastguard Worker {
84*1c60b9acSAndroid Build Coastguard Worker 	return strcmp(((struct sigv4_header *)a)->name,
85*1c60b9acSAndroid Build Coastguard Worker 			((struct sigv4_header *)b)->name);
86*1c60b9acSAndroid Build Coastguard Worker }
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker static int
init_sigv4(struct lws * wsi,struct lws_ss_handle * h,struct sigv4 * s)89*1c60b9acSAndroid Build Coastguard Worker init_sigv4(struct lws *wsi, struct lws_ss_handle *h, struct sigv4 *s)
90*1c60b9acSAndroid Build Coastguard Worker {
91*1c60b9acSAndroid Build Coastguard Worker 	lws_ss_metadata_t *polmd = h->policy->metadata;
92*1c60b9acSAndroid Build Coastguard Worker 	int m = 0;
93*1c60b9acSAndroid Build Coastguard Worker 
94*1c60b9acSAndroid Build Coastguard Worker 	add_header(s, "host:", lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST));
95*1c60b9acSAndroid Build Coastguard Worker 
96*1c60b9acSAndroid Build Coastguard Worker 	while (polmd) {
97*1c60b9acSAndroid Build Coastguard Worker 		if (polmd->value__may_own_heap &&
98*1c60b9acSAndroid Build Coastguard Worker 		    ((uint8_t *)polmd->value__may_own_heap)[0] &&
99*1c60b9acSAndroid Build Coastguard Worker 		    h->metadata[m].value__may_own_heap) {
100*1c60b9acSAndroid Build Coastguard Worker 			/* consider all headers start with "x-amz-" need to be signed */
101*1c60b9acSAndroid Build Coastguard Worker 			if (!strncmp(polmd->value__may_own_heap, "x-amz-",
102*1c60b9acSAndroid Build Coastguard Worker 				     strlen("x-amz-"))) {
103*1c60b9acSAndroid Build Coastguard Worker 				if (add_header(s, polmd->value__may_own_heap,
104*1c60b9acSAndroid Build Coastguard Worker 					       h->metadata[m].value__may_own_heap))
105*1c60b9acSAndroid Build Coastguard Worker 					return -1;
106*1c60b9acSAndroid Build Coastguard Worker 			}
107*1c60b9acSAndroid Build Coastguard Worker 		}
108*1c60b9acSAndroid Build Coastguard Worker 		if (!strcmp(h->metadata[m].name, h->policy->aws_region) &&
109*1c60b9acSAndroid Build Coastguard Worker 		    h->metadata[m].value__may_own_heap)
110*1c60b9acSAndroid Build Coastguard Worker 			s->region = h->metadata[m].value__may_own_heap;
111*1c60b9acSAndroid Build Coastguard Worker 
112*1c60b9acSAndroid Build Coastguard Worker 		if (!strcmp(h->metadata[m].name, h->policy->aws_service) &&
113*1c60b9acSAndroid Build Coastguard Worker 		    h->metadata[m].value__may_own_heap)
114*1c60b9acSAndroid Build Coastguard Worker 			s->service = h->metadata[m].value__may_own_heap;
115*1c60b9acSAndroid Build Coastguard Worker 
116*1c60b9acSAndroid Build Coastguard Worker 		m++;
117*1c60b9acSAndroid Build Coastguard Worker 		polmd = polmd->next;
118*1c60b9acSAndroid Build Coastguard Worker 	}
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 	qsort(s->headers, s->hnum, sizeof(struct sigv4_header), cmp_header);
121*1c60b9acSAndroid Build Coastguard Worker 
122*1c60b9acSAndroid Build Coastguard Worker #if 0
123*1c60b9acSAndroid Build Coastguard Worker 	do {
124*1c60b9acSAndroid Build Coastguard Worker 		int i;
125*1c60b9acSAndroid Build Coastguard Worker 		for (i= 0; i<s->hnum; i++)
126*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s hdr %s %s\n", __func__,
127*1c60b9acSAndroid Build Coastguard Worker 					s->headers[i].name, s->headers[i].value);
128*1c60b9acSAndroid Build Coastguard Worker 
129*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("%s service: %s region: %s\n", __func__,
130*1c60b9acSAndroid Build Coastguard Worker 				s->service, s->region);
131*1c60b9acSAndroid Build Coastguard Worker 	} while(0);
132*1c60b9acSAndroid Build Coastguard Worker #endif
133*1c60b9acSAndroid Build Coastguard Worker 
134*1c60b9acSAndroid Build Coastguard Worker 	return 0;
135*1c60b9acSAndroid Build Coastguard Worker }
136*1c60b9acSAndroid Build Coastguard Worker 
137*1c60b9acSAndroid Build Coastguard Worker static void
bin2hex(uint8_t * in,size_t len,char * out)138*1c60b9acSAndroid Build Coastguard Worker bin2hex(uint8_t *in, size_t len, char *out)
139*1c60b9acSAndroid Build Coastguard Worker {
140*1c60b9acSAndroid Build Coastguard Worker 	static const char *hex = "0123456789abcdef";
141*1c60b9acSAndroid Build Coastguard Worker 	size_t n;
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < len; n++) {
144*1c60b9acSAndroid Build Coastguard Worker 		*out++ = hex[(in[n] >> 4) & 0xf];
145*1c60b9acSAndroid Build Coastguard Worker 		*out++ = hex[in[n] & 15];
146*1c60b9acSAndroid Build Coastguard Worker 	}
147*1c60b9acSAndroid Build Coastguard Worker 	*out = '\0';
148*1c60b9acSAndroid Build Coastguard Worker }
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker static int
hmacsha256(const uint8_t * key,size_t keylen,const uint8_t * txt,size_t txtlen,uint8_t * digest)151*1c60b9acSAndroid Build Coastguard Worker hmacsha256(const uint8_t *key, size_t keylen, const uint8_t *txt,
152*1c60b9acSAndroid Build Coastguard Worker 			size_t txtlen, uint8_t *digest)
153*1c60b9acSAndroid Build Coastguard Worker {
154*1c60b9acSAndroid Build Coastguard Worker 	struct lws_genhmac_ctx hmacctx;
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker 	if (lws_genhmac_init(&hmacctx, LWS_GENHMAC_TYPE_SHA256,
157*1c60b9acSAndroid Build Coastguard Worker 				key, keylen))
158*1c60b9acSAndroid Build Coastguard Worker 		return -1;
159*1c60b9acSAndroid Build Coastguard Worker 
160*1c60b9acSAndroid Build Coastguard Worker 	if (lws_genhmac_update(&hmacctx, txt, txtlen)) {
161*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: hmac computation failed\n", __func__);
162*1c60b9acSAndroid Build Coastguard Worker 		lws_genhmac_destroy(&hmacctx, NULL);
163*1c60b9acSAndroid Build Coastguard Worker 		return -1;
164*1c60b9acSAndroid Build Coastguard Worker 	}
165*1c60b9acSAndroid Build Coastguard Worker 
166*1c60b9acSAndroid Build Coastguard Worker 	if (lws_genhmac_destroy(&hmacctx, digest)) {
167*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: problem destroying hmac\n", __func__);
168*1c60b9acSAndroid Build Coastguard Worker 		return -1;
169*1c60b9acSAndroid Build Coastguard Worker 	}
170*1c60b9acSAndroid Build Coastguard Worker 
171*1c60b9acSAndroid Build Coastguard Worker 	return 0;
172*1c60b9acSAndroid Build Coastguard Worker }
173*1c60b9acSAndroid Build Coastguard Worker 
174*1c60b9acSAndroid Build Coastguard Worker /* cut the last byte of the str */
hash_update_bite_str(struct lws_genhash_ctx * ctx,const char * str)175*1c60b9acSAndroid Build Coastguard Worker static inline int hash_update_bite_str(struct lws_genhash_ctx *ctx, const char * str)
176*1c60b9acSAndroid Build Coastguard Worker {
177*1c60b9acSAndroid Build Coastguard Worker 	int ret = 0;
178*1c60b9acSAndroid Build Coastguard Worker 	if ((ret = lws_genhash_update(ctx, (void *)str, strlen(str)-1))) {
179*1c60b9acSAndroid Build Coastguard Worker 		lws_genhash_destroy(ctx, NULL);
180*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s err %d line \n", __func__, ret);
181*1c60b9acSAndroid Build Coastguard Worker 	}
182*1c60b9acSAndroid Build Coastguard Worker 	return ret;
183*1c60b9acSAndroid Build Coastguard Worker }
184*1c60b9acSAndroid Build Coastguard Worker 
hash_update_str(struct lws_genhash_ctx * ctx,const char * str)185*1c60b9acSAndroid Build Coastguard Worker static inline int hash_update_str(struct lws_genhash_ctx *ctx, const char * str)
186*1c60b9acSAndroid Build Coastguard Worker {
187*1c60b9acSAndroid Build Coastguard Worker 	int ret = 0;
188*1c60b9acSAndroid Build Coastguard Worker 	if ((ret = lws_genhash_update(ctx, (void *)str, strlen(str)))) {
189*1c60b9acSAndroid Build Coastguard Worker 		lws_genhash_destroy(ctx, NULL);
190*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s err %d \n", __func__, ret);
191*1c60b9acSAndroid Build Coastguard Worker 	}
192*1c60b9acSAndroid Build Coastguard Worker 	return ret;
193*1c60b9acSAndroid Build Coastguard Worker }
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker static int
build_sign_string(struct lws * wsi,char * buf,size_t bufsz,struct lws_ss_handle * h,struct sigv4 * s)196*1c60b9acSAndroid Build Coastguard Worker build_sign_string(struct lws *wsi, char *buf, size_t bufsz,
197*1c60b9acSAndroid Build Coastguard Worker 		struct lws_ss_handle *h, struct sigv4 *s)
198*1c60b9acSAndroid Build Coastguard Worker {
199*1c60b9acSAndroid Build Coastguard Worker 	char hash[65], *end = &buf[bufsz - 1], *start;
200*1c60b9acSAndroid Build Coastguard Worker 	struct lws_genhash_ctx hash_ctx;
201*1c60b9acSAndroid Build Coastguard Worker 	uint8_t hash_bin[32];
202*1c60b9acSAndroid Build Coastguard Worker 	int i, ret = 0;
203*1c60b9acSAndroid Build Coastguard Worker 
204*1c60b9acSAndroid Build Coastguard Worker 	start = buf;
205*1c60b9acSAndroid Build Coastguard Worker 
206*1c60b9acSAndroid Build Coastguard Worker 	if ((ret = lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))) {
207*1c60b9acSAndroid Build Coastguard Worker 		lws_genhash_destroy(&hash_ctx, NULL);
208*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s genhash init err %d \n", __func__, ret);
209*1c60b9acSAndroid Build Coastguard Worker 		return -1;
210*1c60b9acSAndroid Build Coastguard Worker 	}
211*1c60b9acSAndroid Build Coastguard Worker 	/*
212*1c60b9acSAndroid Build Coastguard Worker 	 * hash canonical_request
213*1c60b9acSAndroid Build Coastguard Worker 	 */
214*1c60b9acSAndroid Build Coastguard Worker 
215*1c60b9acSAndroid Build Coastguard Worker 	if (hash_update_str(&hash_ctx, h->policy->u.http.method) ||
216*1c60b9acSAndroid Build Coastguard Worker 			hash_update_str(&hash_ctx, "\n"))
217*1c60b9acSAndroid Build Coastguard Worker 		return -1;
218*1c60b9acSAndroid Build Coastguard Worker 	if (hash_update_str(&hash_ctx, lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_URI)) ||
219*1c60b9acSAndroid Build Coastguard Worker 			hash_update_str(&hash_ctx, "\n"))
220*1c60b9acSAndroid Build Coastguard Worker 		return -1;
221*1c60b9acSAndroid Build Coastguard Worker 
222*1c60b9acSAndroid Build Coastguard Worker 	/* TODO, append query string */
223*1c60b9acSAndroid Build Coastguard Worker 	if (hash_update_str(&hash_ctx, "\n"))
224*1c60b9acSAndroid Build Coastguard Worker 		return -1;
225*1c60b9acSAndroid Build Coastguard Worker 
226*1c60b9acSAndroid Build Coastguard Worker 	for (i = 0; i < s->hnum; i++) {
227*1c60b9acSAndroid Build Coastguard Worker 		if (hash_update_str(&hash_ctx, s->headers[i].name) ||
228*1c60b9acSAndroid Build Coastguard Worker 		    hash_update_str(&hash_ctx, s->headers[i].value) ||
229*1c60b9acSAndroid Build Coastguard Worker 		    hash_update_str(&hash_ctx, "\n"))
230*1c60b9acSAndroid Build Coastguard Worker 		return -1;
231*1c60b9acSAndroid Build Coastguard Worker 
232*1c60b9acSAndroid Build Coastguard Worker 	}
233*1c60b9acSAndroid Build Coastguard Worker 	if (hash_update_str(&hash_ctx, "\n"))
234*1c60b9acSAndroid Build Coastguard Worker 		return -1;
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 	for (i = 0; i < s->hnum-1; i++) {
237*1c60b9acSAndroid Build Coastguard Worker 		if (hash_update_bite_str(&hash_ctx, s->headers[i].name) ||
238*1c60b9acSAndroid Build Coastguard Worker 		    hash_update_str(&hash_ctx, ";"))
239*1c60b9acSAndroid Build Coastguard Worker 			return -1;
240*1c60b9acSAndroid Build Coastguard Worker 	}
241*1c60b9acSAndroid Build Coastguard Worker 	if (hash_update_bite_str(&hash_ctx, s->headers[i].name) ||
242*1c60b9acSAndroid Build Coastguard Worker 	    hash_update_str(&hash_ctx, "\n") ||
243*1c60b9acSAndroid Build Coastguard Worker 	    hash_update_str(&hash_ctx, s->payload_hash))
244*1c60b9acSAndroid Build Coastguard Worker 		return -1;
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 	if ((ret = lws_genhash_destroy(&hash_ctx, hash_bin))) {
247*1c60b9acSAndroid Build Coastguard Worker 		lws_genhash_destroy(&hash_ctx, NULL);
248*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s lws_genhash error \n", __func__);
249*1c60b9acSAndroid Build Coastguard Worker 		return -1;
250*1c60b9acSAndroid Build Coastguard Worker 	}
251*1c60b9acSAndroid Build Coastguard Worker 
252*1c60b9acSAndroid Build Coastguard Worker 	bin2hex(hash_bin, sizeof(hash_bin), hash);
253*1c60b9acSAndroid Build Coastguard Worker 	/*
254*1c60b9acSAndroid Build Coastguard Worker 	 * build sign string like the following
255*1c60b9acSAndroid Build Coastguard Worker 	 *
256*1c60b9acSAndroid Build Coastguard Worker 	 * "AWS4-HMAC-SHA256" + "\n" +
257*1c60b9acSAndroid Build Coastguard Worker 	 * timeStampISO8601Format + "\n" +
258*1c60b9acSAndroid Build Coastguard Worker 	 * date.Format(<YYYYMMDD>) + "/" + <region> + "/" + <service> + "/aws4_request" + "\n" +
259*1c60b9acSAndroid Build Coastguard Worker 	 * Hex(SHA256Hash(<CanonicalRequest>))
260*1c60b9acSAndroid Build Coastguard Worker 	 */
261*1c60b9acSAndroid Build Coastguard Worker 	buf = start;
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s\n",
264*1c60b9acSAndroid Build Coastguard Worker 							"AWS4-HMAC-SHA256");
265*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s\n",
266*1c60b9acSAndroid Build Coastguard Worker 							s->timestamp);
267*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s/%s/%s/%s\n",
268*1c60b9acSAndroid Build Coastguard Worker 				s->ymd, s->region, s->service, "aws4_request");
269*1c60b9acSAndroid Build Coastguard Worker 
270*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s", hash);
271*1c60b9acSAndroid Build Coastguard Worker 	*buf++ = '\0';
272*1c60b9acSAndroid Build Coastguard Worker 
273*1c60b9acSAndroid Build Coastguard Worker 	assert(buf <= start + bufsz);
274*1c60b9acSAndroid Build Coastguard Worker 
275*1c60b9acSAndroid Build Coastguard Worker 	return 0;
276*1c60b9acSAndroid Build Coastguard Worker }
277*1c60b9acSAndroid Build Coastguard Worker 
278*1c60b9acSAndroid Build Coastguard Worker /*
279*1c60b9acSAndroid Build Coastguard Worker  * DateKey              = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>")
280*1c60b9acSAndroid Build Coastguard Worker  * DateRegionKey        = HMAC-SHA256(<DateKey>, "<aws-region>")
281*1c60b9acSAndroid Build Coastguard Worker  * DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>")
282*1c60b9acSAndroid Build Coastguard Worker  * SigningKey           = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")
283*1c60b9acSAndroid Build Coastguard Worker  */
284*1c60b9acSAndroid Build Coastguard Worker static int
calc_signing_key(struct lws * wsi,struct lws_ss_handle * h,struct sigv4 * s,uint8_t * sign_key)285*1c60b9acSAndroid Build Coastguard Worker calc_signing_key(struct lws *wsi, struct lws_ss_handle *h,
286*1c60b9acSAndroid Build Coastguard Worker 		struct sigv4 *s, uint8_t *sign_key)
287*1c60b9acSAndroid Build Coastguard Worker {
288*1c60b9acSAndroid Build Coastguard Worker 	uint8_t key[128], date_key[32], and_region_key[32],
289*1c60b9acSAndroid Build Coastguard Worker 		and_service_key[32], *kb;
290*1c60b9acSAndroid Build Coastguard Worker 	lws_system_blob_t *ab;
291*1c60b9acSAndroid Build Coastguard Worker 	size_t keylen;
292*1c60b9acSAndroid Build Coastguard Worker 	int n;
293*1c60b9acSAndroid Build Coastguard Worker 
294*1c60b9acSAndroid Build Coastguard Worker 	ab = lws_system_get_blob(wsi->a.context,
295*1c60b9acSAndroid Build Coastguard Worker 				 blob_idx[h->policy->auth->blob_index],
296*1c60b9acSAndroid Build Coastguard Worker 				 LWS_SS_SIGV4_KEY);
297*1c60b9acSAndroid Build Coastguard Worker 	if (!ab)
298*1c60b9acSAndroid Build Coastguard Worker 		return -1;
299*1c60b9acSAndroid Build Coastguard Worker 
300*1c60b9acSAndroid Build Coastguard Worker 	kb = key;
301*1c60b9acSAndroid Build Coastguard Worker 
302*1c60b9acSAndroid Build Coastguard Worker 	*kb++ = 'A';
303*1c60b9acSAndroid Build Coastguard Worker 	*kb++ = 'W';
304*1c60b9acSAndroid Build Coastguard Worker 	*kb++ = 'S';
305*1c60b9acSAndroid Build Coastguard Worker 	*kb++ = '4';
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	keylen = sizeof(key) - 4;
308*1c60b9acSAndroid Build Coastguard Worker 	if (lws_system_blob_get_size(ab) > keylen - 1)
309*1c60b9acSAndroid Build Coastguard Worker 		return -1;
310*1c60b9acSAndroid Build Coastguard Worker 
311*1c60b9acSAndroid Build Coastguard Worker 	n = lws_system_blob_get(ab, kb, &keylen, 0);
312*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
313*1c60b9acSAndroid Build Coastguard Worker 		return -1;
314*1c60b9acSAndroid Build Coastguard Worker 
315*1c60b9acSAndroid Build Coastguard Worker 	kb[keylen] = '\0';
316*1c60b9acSAndroid Build Coastguard Worker 
317*1c60b9acSAndroid Build Coastguard Worker 	hmacsha256((const uint8_t *)key, strlen((const char *)key),
318*1c60b9acSAndroid Build Coastguard Worker 		   (const uint8_t *)s->ymd, strlen(s->ymd), date_key);
319*1c60b9acSAndroid Build Coastguard Worker 
320*1c60b9acSAndroid Build Coastguard Worker 	hmacsha256(date_key, sizeof(date_key), (const uint8_t *)s->region,
321*1c60b9acSAndroid Build Coastguard Worker 		   strlen(s->region), and_region_key);
322*1c60b9acSAndroid Build Coastguard Worker 
323*1c60b9acSAndroid Build Coastguard Worker 	hmacsha256(and_region_key, sizeof(and_region_key),
324*1c60b9acSAndroid Build Coastguard Worker 		   (const uint8_t *)s->service,
325*1c60b9acSAndroid Build Coastguard Worker 		   strlen(s->service), and_service_key);
326*1c60b9acSAndroid Build Coastguard Worker 
327*1c60b9acSAndroid Build Coastguard Worker 	hmacsha256(and_service_key, sizeof(and_service_key),
328*1c60b9acSAndroid Build Coastguard Worker 		   (uint8_t *)"aws4_request",
329*1c60b9acSAndroid Build Coastguard Worker 		   strlen("aws4_request"), sign_key);
330*1c60b9acSAndroid Build Coastguard Worker 
331*1c60b9acSAndroid Build Coastguard Worker 	return 0;
332*1c60b9acSAndroid Build Coastguard Worker }
333*1c60b9acSAndroid Build Coastguard Worker 
334*1c60b9acSAndroid Build Coastguard Worker /* Sample auth string:
335*1c60b9acSAndroid Build Coastguard Worker  *
336*1c60b9acSAndroid Build Coastguard Worker  * 'Authorization: AWS4-HMAC-SHA256 Credential=AKIAVHWASOFE7TJ7ZUQY/20200731/us-west-2/s3/aws4_request,
337*1c60b9acSAndroid Build Coastguard Worker * SignedHeaders=host;x-amz-content-sha256;x-amz-date, \
338*1c60b9acSAndroid Build Coastguard Worker * Signature=ad9fb75ff3b46c7990e3e8f090abfdd6c01fd67761a517111694377e20698377'
339*1c60b9acSAndroid Build Coastguard Worker */
340*1c60b9acSAndroid Build Coastguard Worker static int
build_auth_string(struct lws * wsi,char * buf,size_t bufsz,struct lws_ss_handle * h,struct sigv4 * s,uint8_t * signature_bin)341*1c60b9acSAndroid Build Coastguard Worker build_auth_string(struct lws *wsi, char * buf, size_t bufsz,
342*1c60b9acSAndroid Build Coastguard Worker 		struct lws_ss_handle *h, struct sigv4 *s,
343*1c60b9acSAndroid Build Coastguard Worker 		uint8_t *signature_bin)
344*1c60b9acSAndroid Build Coastguard Worker {
345*1c60b9acSAndroid Build Coastguard Worker 	char *start = buf, *end = &buf[bufsz - 1];
346*1c60b9acSAndroid Build Coastguard Worker 	char *c;
347*1c60b9acSAndroid Build Coastguard Worker 	lws_system_blob_t *ab;
348*1c60b9acSAndroid Build Coastguard Worker 	size_t keyidlen = 128; // max keyid len is 128
349*1c60b9acSAndroid Build Coastguard Worker 	int n;
350*1c60b9acSAndroid Build Coastguard Worker 
351*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s",
352*1c60b9acSAndroid Build Coastguard Worker 			    "AWS4-HMAC-SHA256 ");
353*1c60b9acSAndroid Build Coastguard Worker 
354*1c60b9acSAndroid Build Coastguard Worker 	ab = lws_system_get_blob(wsi->a.context,
355*1c60b9acSAndroid Build Coastguard Worker 				 blob_idx[h->policy->auth->blob_index],
356*1c60b9acSAndroid Build Coastguard Worker 				 LWS_SS_SIGV4_KEYID);
357*1c60b9acSAndroid Build Coastguard Worker 	if (!ab)
358*1c60b9acSAndroid Build Coastguard Worker 		return -1;
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s",
361*1c60b9acSAndroid Build Coastguard Worker 							"Credential=");
362*1c60b9acSAndroid Build Coastguard Worker 	n = lws_system_blob_get(ab,(uint8_t *)buf, &keyidlen, 0);
363*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0)
364*1c60b9acSAndroid Build Coastguard Worker 		return -1;
365*1c60b9acSAndroid Build Coastguard Worker 	buf += keyidlen;
366*1c60b9acSAndroid Build Coastguard Worker 
367*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "/%s/%s/%s/%s, ",
368*1c60b9acSAndroid Build Coastguard Worker 				s->ymd, s->region, s->service, "aws4_request");
369*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf), "%s",
370*1c60b9acSAndroid Build Coastguard Worker 							"SignedHeaders=");
371*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < s->hnum; n++) {
372*1c60b9acSAndroid Build Coastguard Worker 		buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf),
373*1c60b9acSAndroid Build Coastguard Worker 					"%s",s->headers[n].name);
374*1c60b9acSAndroid Build Coastguard Worker 		buf--; /* remove ':' */
375*1c60b9acSAndroid Build Coastguard Worker 		*buf++ = ';';
376*1c60b9acSAndroid Build Coastguard Worker 	}
377*1c60b9acSAndroid Build Coastguard Worker 	c = buf - 1;
378*1c60b9acSAndroid Build Coastguard Worker 	*c = ','; /* overwrite ';' back to ',' */
379*1c60b9acSAndroid Build Coastguard Worker 
380*1c60b9acSAndroid Build Coastguard Worker 	buf += lws_snprintf(buf, lws_ptr_diff_size_t(end, buf),
381*1c60b9acSAndroid Build Coastguard Worker 			    "%s", " Signature=");
382*1c60b9acSAndroid Build Coastguard Worker 	bin2hex(signature_bin, 32, buf);
383*1c60b9acSAndroid Build Coastguard Worker 
384*1c60b9acSAndroid Build Coastguard Worker 	assert(buf+65 <= start + bufsz);
385*1c60b9acSAndroid Build Coastguard Worker 
386*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s %s\n", __func__, start);
387*1c60b9acSAndroid Build Coastguard Worker 
388*1c60b9acSAndroid Build Coastguard Worker 	return 0;
389*1c60b9acSAndroid Build Coastguard Worker 
390*1c60b9acSAndroid Build Coastguard Worker }
391*1c60b9acSAndroid Build Coastguard Worker 
392*1c60b9acSAndroid Build Coastguard Worker int
lws_ss_apply_sigv4(struct lws * wsi,struct lws_ss_handle * h,unsigned char ** p,unsigned char * end)393*1c60b9acSAndroid Build Coastguard Worker lws_ss_apply_sigv4(struct lws *wsi, struct lws_ss_handle *h,
394*1c60b9acSAndroid Build Coastguard Worker 		     unsigned char **p, unsigned char *end)
395*1c60b9acSAndroid Build Coastguard Worker {
396*1c60b9acSAndroid Build Coastguard Worker 	uint8_t buf[512], sign_key[32], signature_bin[32], *bp;
397*1c60b9acSAndroid Build Coastguard Worker 	struct sigv4 s;
398*1c60b9acSAndroid Build Coastguard Worker 
399*1c60b9acSAndroid Build Coastguard Worker 	memset(&s, 0, sizeof(s));
400*1c60b9acSAndroid Build Coastguard Worker 
401*1c60b9acSAndroid Build Coastguard Worker 	bp = buf;
402*1c60b9acSAndroid Build Coastguard Worker 
403*1c60b9acSAndroid Build Coastguard Worker 	init_sigv4(wsi, h, &s);
404*1c60b9acSAndroid Build Coastguard Worker 	if (!s.timestamp || !s.payload_hash) {
405*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s missing headers\n", __func__);
406*1c60b9acSAndroid Build Coastguard Worker 		return -1;
407*1c60b9acSAndroid Build Coastguard Worker 	}
408*1c60b9acSAndroid Build Coastguard Worker 
409*1c60b9acSAndroid Build Coastguard Worker 	if (build_sign_string(wsi, (char *)bp, sizeof(buf), h, &s))
410*1c60b9acSAndroid Build Coastguard Worker 		return -1;
411*1c60b9acSAndroid Build Coastguard Worker 
412*1c60b9acSAndroid Build Coastguard Worker 	if (calc_signing_key(wsi, h, &s, sign_key))
413*1c60b9acSAndroid Build Coastguard Worker 		return -1;
414*1c60b9acSAndroid Build Coastguard Worker 
415*1c60b9acSAndroid Build Coastguard Worker 	hmacsha256(sign_key, sizeof(sign_key), (const uint8_t *)buf,
416*1c60b9acSAndroid Build Coastguard Worker 			      strlen((const char *)buf), signature_bin);
417*1c60b9acSAndroid Build Coastguard Worker 
418*1c60b9acSAndroid Build Coastguard Worker 	bp = buf; /* reuse for auth_str */
419*1c60b9acSAndroid Build Coastguard Worker 	if (build_auth_string(wsi, (char *)bp, sizeof(buf), h, &s,
420*1c60b9acSAndroid Build Coastguard Worker 				signature_bin))
421*1c60b9acSAndroid Build Coastguard Worker 		return -1;
422*1c60b9acSAndroid Build Coastguard Worker 
423*1c60b9acSAndroid Build Coastguard Worker 	if (lws_add_http_header_by_name(wsi,
424*1c60b9acSAndroid Build Coastguard Worker 					(const uint8_t *)"Authorization:", buf,
425*1c60b9acSAndroid Build Coastguard Worker 					(int)strlen((const char*)buf), p, end))
426*1c60b9acSAndroid Build Coastguard Worker 		return -1;
427*1c60b9acSAndroid Build Coastguard Worker 
428*1c60b9acSAndroid Build Coastguard Worker 	return 0;
429*1c60b9acSAndroid Build Coastguard Worker }
430*1c60b9acSAndroid Build Coastguard Worker 
431*1c60b9acSAndroid Build Coastguard Worker int
lws_ss_sigv4_set_aws_key(struct lws_context * context,uint8_t idx,const char * keyid,const char * key)432*1c60b9acSAndroid Build Coastguard Worker lws_ss_sigv4_set_aws_key(struct lws_context* context, uint8_t idx,
433*1c60b9acSAndroid Build Coastguard Worker 		                const char * keyid, const char * key)
434*1c60b9acSAndroid Build Coastguard Worker {
435*1c60b9acSAndroid Build Coastguard Worker 	const char * s[] = { keyid, key };
436*1c60b9acSAndroid Build Coastguard Worker 	lws_system_blob_t *ab;
437*1c60b9acSAndroid Build Coastguard Worker 	int i;
438*1c60b9acSAndroid Build Coastguard Worker 
439*1c60b9acSAndroid Build Coastguard Worker 	if (idx > LWS_ARRAY_SIZE(blob_idx))
440*1c60b9acSAndroid Build Coastguard Worker 		return -1;
441*1c60b9acSAndroid Build Coastguard Worker 
442*1c60b9acSAndroid Build Coastguard Worker 	for (i = 0; i < LWS_SS_SIGV4_BLOB_SLOTS; i++) {
443*1c60b9acSAndroid Build Coastguard Worker 		ab = lws_system_get_blob(context, blob_idx[idx], i);
444*1c60b9acSAndroid Build Coastguard Worker 		if (!ab)
445*1c60b9acSAndroid Build Coastguard Worker 			return -1;
446*1c60b9acSAndroid Build Coastguard Worker 
447*1c60b9acSAndroid Build Coastguard Worker 		lws_system_blob_heap_empty(ab);
448*1c60b9acSAndroid Build Coastguard Worker 
449*1c60b9acSAndroid Build Coastguard Worker 		if (lws_system_blob_heap_append(ab, (const uint8_t *)s[i],
450*1c60b9acSAndroid Build Coastguard Worker 						strlen(s[i]))) {
451*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: can't store %d \n", __func__, i);
452*1c60b9acSAndroid Build Coastguard Worker 
453*1c60b9acSAndroid Build Coastguard Worker 			return -1;
454*1c60b9acSAndroid Build Coastguard Worker 		}
455*1c60b9acSAndroid Build Coastguard Worker 	}
456*1c60b9acSAndroid Build Coastguard Worker 
457*1c60b9acSAndroid Build Coastguard Worker 	return 0;
458*1c60b9acSAndroid Build Coastguard Worker }
459*1c60b9acSAndroid Build Coastguard Worker 
460*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__) || defined(__APPLE__) || defined(WIN32) || \
461*1c60b9acSAndroid Build Coastguard Worker 	defined(__FreeBSD__) || defined(__NetBSD__) || defined(__ANDROID__) || \
462*1c60b9acSAndroid Build Coastguard Worker 	defined(__sun) || defined(__OpenBSD__)
463*1c60b9acSAndroid Build Coastguard Worker 
464*1c60b9acSAndroid Build Coastguard Worker /* ie, if we have filesystem ops */
465*1c60b9acSAndroid Build Coastguard Worker 
466*1c60b9acSAndroid Build Coastguard Worker int
lws_aws_filesystem_credentials_helper(const char * path,const char * kid,const char * ak,char ** aws_keyid,char ** aws_key)467*1c60b9acSAndroid Build Coastguard Worker lws_aws_filesystem_credentials_helper(const char *path, const char *kid,
468*1c60b9acSAndroid Build Coastguard Worker 				      const char *ak, char **aws_keyid,
469*1c60b9acSAndroid Build Coastguard Worker 				      char **aws_key)
470*1c60b9acSAndroid Build Coastguard Worker {
471*1c60b9acSAndroid Build Coastguard Worker 	char *str = NULL, *val = NULL, *line = NULL, sth[128];
472*1c60b9acSAndroid Build Coastguard Worker 	size_t len = sizeof(sth);
473*1c60b9acSAndroid Build Coastguard Worker 	const char *home = "";
474*1c60b9acSAndroid Build Coastguard Worker 	int i, poff = 0;
475*1c60b9acSAndroid Build Coastguard Worker 	ssize_t rd;
476*1c60b9acSAndroid Build Coastguard Worker 	FILE *fp;
477*1c60b9acSAndroid Build Coastguard Worker 
478*1c60b9acSAndroid Build Coastguard Worker 	*aws_keyid = *aws_key = NULL;
479*1c60b9acSAndroid Build Coastguard Worker 
480*1c60b9acSAndroid Build Coastguard Worker 	if (path[0] == '~') {
481*1c60b9acSAndroid Build Coastguard Worker 		home = getenv("HOME");
482*1c60b9acSAndroid Build Coastguard Worker 		if (home && strlen(home) > sizeof(sth) - 1) /* coverity */
483*1c60b9acSAndroid Build Coastguard Worker 			return -1;
484*1c60b9acSAndroid Build Coastguard Worker 		else {
485*1c60b9acSAndroid Build Coastguard Worker 			if (!home)
486*1c60b9acSAndroid Build Coastguard Worker 				home = "";
487*1c60b9acSAndroid Build Coastguard Worker 
488*1c60b9acSAndroid Build Coastguard Worker 			poff = 1;
489*1c60b9acSAndroid Build Coastguard Worker 		}
490*1c60b9acSAndroid Build Coastguard Worker 	}
491*1c60b9acSAndroid Build Coastguard Worker 	lws_snprintf(sth, sizeof(sth), "%s%s", home, path + poff);
492*1c60b9acSAndroid Build Coastguard Worker 
493*1c60b9acSAndroid Build Coastguard Worker 	fp = fopen(sth, "r");
494*1c60b9acSAndroid Build Coastguard Worker 	if (!fp) {
495*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s can't open '%s'\n", __func__, sth);
496*1c60b9acSAndroid Build Coastguard Worker 
497*1c60b9acSAndroid Build Coastguard Worker 		return -1;
498*1c60b9acSAndroid Build Coastguard Worker 	}
499*1c60b9acSAndroid Build Coastguard Worker 
500*1c60b9acSAndroid Build Coastguard Worker 	while ((rd = getline(&line, &len, fp)) != -1) {
501*1c60b9acSAndroid Build Coastguard Worker 		for (i = 0; i < 2; i++) {
502*1c60b9acSAndroid Build Coastguard Worker 			size_t slen;
503*1c60b9acSAndroid Build Coastguard Worker 
504*1c60b9acSAndroid Build Coastguard Worker 			if (strncmp(line, i ? kid : ak, strlen(i ? kid : ak)))
505*1c60b9acSAndroid Build Coastguard Worker 				continue;
506*1c60b9acSAndroid Build Coastguard Worker 
507*1c60b9acSAndroid Build Coastguard Worker 			str = strchr(line, '=');
508*1c60b9acSAndroid Build Coastguard Worker 			if (!str)
509*1c60b9acSAndroid Build Coastguard Worker 				continue;
510*1c60b9acSAndroid Build Coastguard Worker 
511*1c60b9acSAndroid Build Coastguard Worker 			str++;
512*1c60b9acSAndroid Build Coastguard Worker 
513*1c60b9acSAndroid Build Coastguard Worker 			/* only read the first key for each */
514*1c60b9acSAndroid Build Coastguard Worker 			if (*(i ? aws_keyid : aws_key))
515*1c60b9acSAndroid Build Coastguard Worker 				continue;
516*1c60b9acSAndroid Build Coastguard Worker 
517*1c60b9acSAndroid Build Coastguard Worker 			/*
518*1c60b9acSAndroid Build Coastguard Worker 			 * Trim whitespace from the start and end
519*1c60b9acSAndroid Build Coastguard Worker 			 */
520*1c60b9acSAndroid Build Coastguard Worker 
521*1c60b9acSAndroid Build Coastguard Worker 			slen = (size_t)(rd - lws_ptr_diff(str, line));
522*1c60b9acSAndroid Build Coastguard Worker 
523*1c60b9acSAndroid Build Coastguard Worker 			while (slen && *str == ' ') {
524*1c60b9acSAndroid Build Coastguard Worker 				str++;
525*1c60b9acSAndroid Build Coastguard Worker 				slen--;
526*1c60b9acSAndroid Build Coastguard Worker 			}
527*1c60b9acSAndroid Build Coastguard Worker 
528*1c60b9acSAndroid Build Coastguard Worker 			while (slen && (str[slen - 1] == '\r' ||
529*1c60b9acSAndroid Build Coastguard Worker 					str[slen - 1] == '\n' ||
530*1c60b9acSAndroid Build Coastguard Worker 					str[slen - 1] == ' '))
531*1c60b9acSAndroid Build Coastguard Worker 				slen--;
532*1c60b9acSAndroid Build Coastguard Worker 
533*1c60b9acSAndroid Build Coastguard Worker 			val = malloc(slen + 1);
534*1c60b9acSAndroid Build Coastguard Worker 			if (!val)
535*1c60b9acSAndroid Build Coastguard Worker 				goto bail;
536*1c60b9acSAndroid Build Coastguard Worker 
537*1c60b9acSAndroid Build Coastguard Worker 			strncpy(val, str, slen);
538*1c60b9acSAndroid Build Coastguard Worker 			val[slen] = '\0';
539*1c60b9acSAndroid Build Coastguard Worker 
540*1c60b9acSAndroid Build Coastguard Worker 			*(i ? aws_keyid : aws_key) = val;
541*1c60b9acSAndroid Build Coastguard Worker 
542*1c60b9acSAndroid Build Coastguard Worker 		}
543*1c60b9acSAndroid Build Coastguard Worker 	}
544*1c60b9acSAndroid Build Coastguard Worker 
545*1c60b9acSAndroid Build Coastguard Worker bail:
546*1c60b9acSAndroid Build Coastguard Worker 	fclose(fp);
547*1c60b9acSAndroid Build Coastguard Worker 
548*1c60b9acSAndroid Build Coastguard Worker 	if (line)
549*1c60b9acSAndroid Build Coastguard Worker 		free(line);
550*1c60b9acSAndroid Build Coastguard Worker 
551*1c60b9acSAndroid Build Coastguard Worker 	if (!*aws_keyid || !*aws_key) {
552*1c60b9acSAndroid Build Coastguard Worker 		if (*aws_keyid) {
553*1c60b9acSAndroid Build Coastguard Worker 			free(*aws_keyid);
554*1c60b9acSAndroid Build Coastguard Worker 			*aws_keyid = NULL;
555*1c60b9acSAndroid Build Coastguard Worker 		}
556*1c60b9acSAndroid Build Coastguard Worker 		if (*aws_key) {
557*1c60b9acSAndroid Build Coastguard Worker 			free(*aws_key);
558*1c60b9acSAndroid Build Coastguard Worker 			*aws_key = NULL;
559*1c60b9acSAndroid Build Coastguard Worker 		}
560*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s can't find aws credentials! \
561*1c60b9acSAndroid Build Coastguard Worker 				please check %s\n", __func__, path);
562*1c60b9acSAndroid Build Coastguard Worker 		return -1;
563*1c60b9acSAndroid Build Coastguard Worker 	}
564*1c60b9acSAndroid Build Coastguard Worker 
565*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: '%s' '%s'\n", __func__, *aws_keyid, *aws_key);
566*1c60b9acSAndroid Build Coastguard Worker 
567*1c60b9acSAndroid Build Coastguard Worker 	return 0;
568*1c60b9acSAndroid Build Coastguard Worker }
569*1c60b9acSAndroid Build Coastguard Worker #endif
570