Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: patches.chromium/0014-new_channelid.patch

Issue 2072073002: Delete bundled copy of OpenSSL and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/openssl@master
Patch Set: Delete bundled copy of OpenSSL and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 diff -burN android-openssl.orig/include/openssl/ssl.h android-openssl/include/op enssl/ssl.h
2 --- android-openssl.orig/include/openssl/ssl.h 2014-05-05 16:45:02.685389339 +0 200
3 +++ android-openssl/include/openssl/ssl.h 2014-05-05 16:46:32.513390565 +0 200
4 @@ -544,6 +544,13 @@
5 #ifndef OPENSSL_NO_SRP
6 char *srp_username;
7 #endif
8 +
9 + /* original_handshake_hash contains the handshake hash (either
10 + * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
11 + * handshake that created a session. This is used by Channel IDs during
12 + * resumption. */
13 + unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
14 + unsigned int original_handshake_hash_len;
15 };
16
17 #endif
18 diff -burN android-openssl.orig/include/openssl/tls1.h android-openssl/include/o penssl/tls1.h
19 --- android-openssl.orig/include/openssl/tls1.h 2014-05-05 16:45:02.689389339 +0 200
20 +++ android-openssl/include/openssl/tls1.h 2014-05-05 16:46:32.517390565 +0 200
21 @@ -249,7 +249,7 @@
22 #endif
23
24 /* This is not an IANA defined extension number */
25 -#define TLSEXT_TYPE_channel_id 30031
26 +#define TLSEXT_TYPE_channel_id 30032
27
28 /* NameType value from RFC 3546 */
29 #define TLSEXT_NAMETYPE_host_name 0
30 diff -burN android-openssl.orig/patches/new_channelid.patch android-openssl/patc hes/new_channelid.patch
31 --- android-openssl.orig/patches/new_channelid.patch 1970-01-01 01:00:00.0000 00000 +0100
32 +++ android-openssl/patches/new_channelid.patch 2014-05-05 16:48:54.429392502 +0 200
33 @@ -0,0 +1,273 @@
34 +diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
35 +index a3944f1..fe92ccf 100644
36 +--- a/include/openssl/ssl.h
37 ++++ b/include/openssl/ssl.h
38 +@@ -547,6 +547,13 @@ struct ssl_session_st
39 + #ifndef OPENSSL_NO_SRP
40 + char *srp_username;
41 + #endif
42 ++
43 ++ /* original_handshake_hash contains the handshake hash (either
44 ++ * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
45 ++ * handshake that created a session. This is used by Channel IDs during
46 ++ * resumption. */
47 ++ unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
48 ++ unsigned int original_handshake_hash_len;
49 + };
50 +
51 + #endif
52 +diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
53 +index c4f69aa..5559486 100644
54 +--- a/include/openssl/tls1.h
55 ++++ b/include/openssl/tls1.h
56 +@@ -255,7 +255,7 @@ extern "C" {
57 + #endif
58 +
59 + /* This is not an IANA defined extension number */
60 +-#define TLSEXT_TYPE_channel_id 30031
61 ++#define TLSEXT_TYPE_channel_id 30032
62 +
63 + /* NameType value from RFC 3546 */
64 + #define TLSEXT_NAMETYPE_host_name 0
65 +diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
66 +index 640df80..d6154c5 100644
67 +--- a/ssl/s3_clnt.c
68 ++++ b/ssl/s3_clnt.c
69 +@@ -583,6 +583,18 @@ int ssl3_connect(SSL *s)
70 + #endif
71 + s->s3->tmp.next_state=SSL3_ST_CR _FINISHED_A;
72 + }
73 ++ if (s->s3->tlsext_channel_id_valid)
74 ++ {
75 ++ /* This is a non-resumption handshake. I f it
76 ++ * involves ChannelID, then record the
77 ++ * handshake hashes at this point in the
78 ++ * session so that any resumption of thi s
79 ++ * session with ChannelID can sign those
80 ++ * hashes. */
81 ++ ret = tls1_record_handshake_hashes_for_c hannel_id(s);
82 ++ if (ret <= 0)
83 ++ goto end;
84 ++ }
85 + }
86 + s->init_num=0;
87 + break;
88 +diff --git a/ssl/ssl.h b/ssl/ssl.h
89 +index a3944f1..fe92ccf 100644
90 +--- a/ssl/ssl.h
91 ++++ b/ssl/ssl.h
92 +@@ -547,6 +547,13 @@ struct ssl_session_st
93 + #ifndef OPENSSL_NO_SRP
94 + char *srp_username;
95 + #endif
96 ++
97 ++ /* original_handshake_hash contains the handshake hash (either
98 ++ * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
99 ++ * handshake that created a session. This is used by Channel IDs during
100 ++ * resumption. */
101 ++ unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
102 ++ unsigned int original_handshake_hash_len;
103 + };
104 +
105 + #endif
106 +diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
107 +index 531a291..c975d31 100644
108 +--- a/ssl/ssl_locl.h
109 ++++ b/ssl/ssl_locl.h
110 +@@ -1102,6 +1102,7 @@ void ssl_free_wbio_buffer(SSL *s);
111 + int tls1_change_cipher_state(SSL *s, int which);
112 + int tls1_setup_key_block(SSL *s);
113 + int tls1_enc(SSL *s, int snd);
114 ++int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len);
115 + int tls1_final_finish_mac(SSL *s,
116 + const char *str, int slen, unsigned char *p);
117 + int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
118 +@@ -1158,6 +1159,7 @@ int tls12_get_sigid(const EVP_PKEY *pk);
119 + const EVP_MD *tls12_get_hash(unsigned char hash_alg);
120 +
121 + int tls1_channel_id_hash(EVP_MD_CTX *ctx, SSL *s);
122 ++int tls1_record_handshake_hashes_for_channel_id(SSL *s);
123 + #endif
124 +
125 + int ssl3_can_cutthrough(const SSL *s);
126 +diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
127 +index 87b7021..d30ce61 100644
128 +--- a/ssl/t1_enc.c
129 ++++ b/ssl/t1_enc.c
130 +@@ -1147,53 +1147,79 @@ int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned c har *out)
131 + return((int)ret);
132 + }
133 +
134 ++/* tls1_handshake_digest calculates the current handshake hash and writes it t o
135 ++ * |out|, which has space for |out_len| bytes. It returns the number of bytes
136 ++ * written or -1 in the event of an error. This function works on a copy of th e
137 ++ * underlying digests so can be called multiple times and prior to the final
138 ++ * update etc. */
139 ++int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len)
140 ++ {
141 ++ const EVP_MD *md;
142 ++ EVP_MD_CTX ctx;
143 ++ int i, err = 0, len = 0;
144 ++ long mask;
145 ++
146 ++ EVP_MD_CTX_init(&ctx);
147 ++
148 ++ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++)
149 ++ {
150 ++ int hash_size;
151 ++ unsigned int digest_len;
152 ++ EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i];
153 ++
154 ++ if ((mask & ssl_get_algorithm2(s)) == 0)
155 ++ continue;
156 ++
157 ++ hash_size = EVP_MD_size(md);
158 ++ if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len)
159 ++ {
160 ++ err = 1;
161 ++ break;
162 ++ }
163 ++
164 ++ if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
165 ++ !EVP_DigestFinal_ex(&ctx, out, &digest_len) ||
166 ++ digest_len != (unsigned int)hash_size) /* internal error */
167 ++ {
168 ++ err = 1;
169 ++ break;
170 ++ }
171 ++ out += digest_len;
172 ++ out_len -= digest_len;
173 ++ len += digest_len;
174 ++ }
175 ++
176 ++ EVP_MD_CTX_cleanup(&ctx);
177 ++
178 ++ if (err != 0)
179 ++ return -1;
180 ++ return len;
181 ++ }
182 ++
183 + int tls1_final_finish_mac(SSL *s,
184 + const char *str, int slen, unsigned char *out)
185 + {
186 +- unsigned int i;
187 +- EVP_MD_CTX ctx;
188 + unsigned char buf[2*EVP_MAX_MD_SIZE];
189 +- unsigned char *q,buf2[12];
190 +- int idx;
191 +- long mask;
192 ++ unsigned char buf2[12];
193 + int err=0;
194 +- const EVP_MD *md;
195 ++ int digests_len;
196 +
197 +- q=buf;
198 +-
199 +- if (s->s3->handshake_buffer)
200 ++ if (s->s3->handshake_buffer)
201 + if (!ssl3_digest_cached_records(s))
202 + return 0;
203 +
204 +- EVP_MD_CTX_init(&ctx);
205 +-
206 +- for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
207 ++ digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
208 ++ if (digests_len < 0)
209 + {
210 +- if (mask & ssl_get_algorithm2(s))
211 +- {
212 +- int hashsize = EVP_MD_size(md);
213 +- if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_ t)(q-buf)))
214 +- {
215 +- /* internal error: 'buf' is too small for this c ipersuite! */
216 +- err = 1;
217 +- }
218 +- else
219 +- {
220 +- EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[id x]);
221 +- EVP_DigestFinal_ex(&ctx,q,&i);
222 +- if (i != (unsigned int)hashsize) /* can't really happen */
223 +- err = 1;
224 +- q+=i;
225 +- }
226 +- }
227 ++ err = 1;
228 ++ digests_len = 0;
229 + }
230 +-
231 ++
232 + if (!tls1_PRF(ssl_get_algorithm2(s),
233 +- str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
234 ++ str,slen, buf, digests_len, NULL,0, NULL,0, NULL,0,
235 + s->session->master_key,s->session->master_key_length,
236 + out,buf2,sizeof buf2))
237 + err = 1;
238 +- EVP_MD_CTX_cleanup(&ctx);
239 +
240 + if (err)
241 + return 0;
242 +diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
243 +index ea7fefa..d7ea9a5 100644
244 +--- a/ssl/t1_lib.c
245 ++++ b/ssl/t1_lib.c
246 +@@ -2684,6 +2684,17 @@ tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s)
247 +
248 + EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic));
249 +
250 ++ if (s->hit)
251 ++ {
252 ++ static const char kResumptionMagic[] = "Resumption";
253 ++ EVP_DigestUpdate(md, kResumptionMagic,
254 ++ sizeof(kResumptionMagic));
255 ++ if (s->session->original_handshake_hash_len == 0)
256 ++ return 0;
257 ++ EVP_DigestUpdate(md, s->session->original_handshake_hash,
258 ++ s->session->original_handshake_hash_len);
259 ++ }
260 ++
261 + EVP_MD_CTX_init(&ctx);
262 + for (i = 0; i < SSL_MAX_DIGEST; i++)
263 + {
264 +@@ -2698,3 +2709,29 @@ tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s)
265 + return 1;
266 + }
267 + #endif
268 ++
269 ++/* tls1_record_handshake_hashes_for_channel_id records the current handshake
270 ++ * hashes in |s->session| so that Channel ID resumptions can sign that data. * /
271 ++int tls1_record_handshake_hashes_for_channel_id(SSL *s)
272 ++ {
273 ++ int digest_len;
274 ++ /* This function should never be called for a resumed session because
275 ++ * the handshake hashes that we wish to record are for the original,
276 ++ * full handshake. */
277 ++ if (s->hit)
278 ++ return -1;
279 ++ /* It only makes sense to call this function if Channel IDs have been
280 ++ * negotiated. */
281 ++ if (!s->s3->tlsext_channel_id_valid)
282 ++ return -1;
283 ++
284 ++ digest_len = tls1_handshake_digest(
285 ++ s, s->session->original_handshake_hash,
286 ++ sizeof(s->session->original_handshake_hash));
287 ++ if (digest_len < 0)
288 ++ return -1;
289 ++
290 ++ s->session->original_handshake_hash_len = digest_len;
291 ++
292 ++ return 1;
293 ++ }
294 +diff --git a/ssl/tls1.h b/ssl/tls1.h
295 +index c4f69aa..5559486 100644
296 +--- a/ssl/tls1.h
297 ++++ b/ssl/tls1.h
298 +@@ -255,7 +255,7 @@ extern "C" {
299 + #endif
300 +
301 + /* This is not an IANA defined extension number */
302 +-#define TLSEXT_TYPE_channel_id 30031
303 ++#define TLSEXT_TYPE_channel_id 30032
304 +
305 + /* NameType value from RFC 3546 */
306 + #define TLSEXT_NAMETYPE_host_name 0
307 diff -burN android-openssl.orig/ssl/s3_clnt.c android-openssl/ssl/s3_clnt.c
308 --- android-openssl.orig/ssl/s3_clnt.c 2014-05-05 16:45:02.785389340 +0200
309 +++ android-openssl/ssl/s3_clnt.c 2014-05-05 16:46:32.525390565 +0200
310 @@ -583,6 +583,18 @@
311 #endif
312 s->s3->tmp.next_state=SSL3_ST_CR _FINISHED_A;
313 }
314 + if (s->s3->tlsext_channel_id_valid)
315 + {
316 + /* This is a non-resumption handshake. I f it
317 + * involves ChannelID, then record the
318 + * handshake hashes at this point in the
319 + * session so that any resumption of thi s
320 + * session with ChannelID can sign those
321 + * hashes. */
322 + ret = tls1_record_handshake_hashes_for_c hannel_id(s);
323 + if (ret <= 0)
324 + goto end;
325 + }
326 }
327 s->init_num=0;
328 break;
329 diff -burN android-openssl.orig/ssl/ssl.h android-openssl/ssl/ssl.h
330 --- android-openssl.orig/ssl/ssl.h 2014-05-05 16:45:02.693389339 +0200
331 +++ android-openssl/ssl/ssl.h 2014-05-05 16:46:32.533390565 +0200
332 @@ -544,6 +544,13 @@
333 #ifndef OPENSSL_NO_SRP
334 char *srp_username;
335 #endif
336 +
337 + /* original_handshake_hash contains the handshake hash (either
338 + * SHA-1+MD5 or SHA-2, depending on TLS version) for the original, full
339 + * handshake that created a session. This is used by Channel IDs during
340 + * resumption. */
341 + unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
342 + unsigned int original_handshake_hash_len;
343 };
344
345 #endif
346 diff -burN android-openssl.orig/ssl/ssl_locl.h android-openssl/ssl/ssl_locl.h
347 --- android-openssl.orig/ssl/ssl_locl.h 2014-05-05 16:45:02.785389340 +0200
348 +++ android-openssl/ssl/ssl_locl.h 2014-05-05 16:46:32.541390565 +0200
349 @@ -1071,6 +1071,7 @@
350 int tls1_change_cipher_state(SSL *s, int which);
351 int tls1_setup_key_block(SSL *s);
352 int tls1_enc(SSL *s, int snd);
353 +int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len);
354 int tls1_final_finish_mac(SSL *s,
355 const char *str, int slen, unsigned char *p);
356 int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *p);
357 @@ -1127,6 +1128,7 @@
358 const EVP_MD *tls12_get_hash(unsigned char hash_alg);
359
360 int tls1_channel_id_hash(EVP_MD_CTX *ctx, SSL *s);
361 +int tls1_record_handshake_hashes_for_channel_id(SSL *s);
362 #endif
363
364 int ssl3_can_cutthrough(const SSL *s);
365 diff -burN android-openssl.orig/ssl/t1_enc.c android-openssl/ssl/t1_enc.c
366 --- android-openssl.orig/ssl/t1_enc.c 2014-05-05 16:45:02.697389339 +0200
367 +++ android-openssl/ssl/t1_enc.c 2014-05-05 16:46:32.545390565 +0200
368 @@ -890,53 +890,79 @@
369 return((int)ret);
370 }
371
372 -int tls1_final_finish_mac(SSL *s,
373 - const char *str, int slen, unsigned char *out)
374 +/* tls1_handshake_digest calculates the current handshake hash and writes it to
375 + * |out|, which has space for |out_len| bytes. It returns the number of bytes
376 + * written or -1 in the event of an error. This function works on a copy of the
377 + * underlying digests so can be called multiple times and prior to the final
378 + * update etc. */
379 +int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len)
380 {
381 - unsigned int i;
382 + const EVP_MD *md;
383 EVP_MD_CTX ctx;
384 - unsigned char buf[2*EVP_MAX_MD_SIZE];
385 - unsigned char *q,buf2[12];
386 - int idx;
387 + int i, err = 0, len = 0;
388 long mask;
389 - int err=0;
390 - const EVP_MD *md;
391 -
392 - q=buf;
393 -
394 - if (s->s3->handshake_buffer)
395 - if (!ssl3_digest_cached_records(s))
396 - return 0;
397
398 EVP_MD_CTX_init(&ctx);
399
400 - for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++)
401 + for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++)
402 {
403 - if (mask & ssl_get_algorithm2(s))
404 - {
405 - int hashsize = EVP_MD_size(md);
406 - if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_ t)(q-buf)))
407 + int hash_size;
408 + unsigned int digest_len;
409 + EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i];
410 +
411 + if ((mask & ssl_get_algorithm2(s)) == 0)
412 + continue;
413 +
414 + hash_size = EVP_MD_size(md);
415 + if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len)
416 {
417 - /* internal error: 'buf' is too small for this c ipersuite! */
418 err = 1;
419 + break;
420 }
421 - else
422 +
423 + if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) ||
424 + !EVP_DigestFinal_ex(&ctx, out, &digest_len) ||
425 + digest_len != (unsigned int)hash_size) /* internal error */
426 {
427 - EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[id x]);
428 - EVP_DigestFinal_ex(&ctx,q,&i);
429 - if (i != (unsigned int)hashsize) /* can't really happen */
430 err = 1;
431 - q+=i;
432 + break;
433 }
434 + out += digest_len;
435 + out_len -= digest_len;
436 + len += digest_len;
437 }
438 +
439 + EVP_MD_CTX_cleanup(&ctx);
440 +
441 + if (err != 0)
442 + return -1;
443 + return len;
444 + }
445 +
446 +int tls1_final_finish_mac(SSL *s,
447 + const char *str, int slen, unsigned char *out)
448 + {
449 + unsigned char buf[2*EVP_MAX_MD_SIZE];
450 + unsigned char buf2[12];
451 + int err=0;
452 + int digests_len;
453 +
454 + if (s->s3->handshake_buffer)
455 + if (!ssl3_digest_cached_records(s))
456 + return 0;
457 +
458 + digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
459 + if (digests_len < 0)
460 + {
461 + err = 1;
462 + digests_len = 0;
463 }
464
465 if (!tls1_PRF(ssl_get_algorithm2(s),
466 - str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
467 + str,slen, buf, digests_len, NULL,0, NULL,0, NULL,0,
468 s->session->master_key,s->session->master_key_length,
469 out,buf2,sizeof buf2))
470 err = 1;
471 - EVP_MD_CTX_cleanup(&ctx);
472
473 if (err)
474 return 0;
475 diff -burN android-openssl.orig/ssl/t1_lib.c android-openssl/ssl/t1_lib.c
476 --- android-openssl.orig/ssl/t1_lib.c 2014-05-05 16:45:02.789389340 +0200
477 +++ android-openssl/ssl/t1_lib.c 2014-05-05 16:46:32.549390565 +0200
478 @@ -2672,6 +2672,17 @@
479
480 EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic));
481
482 + if (s->hit)
483 + {
484 + static const char kResumptionMagic[] = "Resumption";
485 + EVP_DigestUpdate(md, kResumptionMagic,
486 + sizeof(kResumptionMagic));
487 + if (s->session->original_handshake_hash_len == 0)
488 + return 0;
489 + EVP_DigestUpdate(md, s->session->original_handshake_hash,
490 + s->session->original_handshake_hash_len);
491 + }
492 +
493 EVP_MD_CTX_init(&ctx);
494 for (i = 0; i < SSL_MAX_DIGEST; i++)
495 {
496 @@ -2686,3 +2697,29 @@
497 return 1;
498 }
499 #endif
500 +
501 +/* tls1_record_handshake_hashes_for_channel_id records the current handshake
502 + * hashes in |s->session| so that Channel ID resumptions can sign that data. */
503 +int tls1_record_handshake_hashes_for_channel_id(SSL *s)
504 + {
505 + int digest_len;
506 + /* This function should never be called for a resumed session because
507 + * the handshake hashes that we wish to record are for the original,
508 + * full handshake. */
509 + if (s->hit)
510 + return -1;
511 + /* It only makes sense to call this function if Channel IDs have been
512 + * negotiated. */
513 + if (!s->s3->tlsext_channel_id_valid)
514 + return -1;
515 +
516 + digest_len = tls1_handshake_digest(
517 + s, s->session->original_handshake_hash,
518 + sizeof(s->session->original_handshake_hash));
519 + if (digest_len < 0)
520 + return -1;
521 +
522 + s->session->original_handshake_hash_len = digest_len;
523 +
524 + return 1;
525 + }
526 diff -burN android-openssl.orig/ssl/tls1.h android-openssl/ssl/tls1.h
527 --- android-openssl.orig/ssl/tls1.h 2014-05-05 16:45:02.697389339 +0200
528 +++ android-openssl/ssl/tls1.h 2014-05-05 16:46:32.553390566 +0200
529 @@ -249,7 +249,7 @@
530 #endif
531
532 /* This is not an IANA defined extension number */
533 -#define TLSEXT_TYPE_channel_id 30031
534 +#define TLSEXT_TYPE_channel_id 30032
535
536 /* NameType value from RFC 3546 */
537 #define TLSEXT_NAMETYPE_host_name 0
OLDNEW
« no previous file with comments | « patches.chromium/0013-reorder_extensions.patch ('k') | patches.chromium/0015-export_certificate_types.patch » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698