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

Side by Side Diff: openssl/apps/enc.c

Issue 9254031: Upgrade chrome's OpenSSL to same version Android ships with. (Closed) Base URL: http://src.chromium.org/svn/trunk/deps/third_party/openssl/
Patch Set: '' Created 8 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « openssl/apps/ecparam.c ('k') | openssl/apps/engine.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* apps/enc.c */ 1 /* apps/enc.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * This package is an SSL implementation written 5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com). 6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL. 7 * The implementation was written so as to conform with Netscapes SSL.
8 * 8 *
9 * This library is free for commercial and non-commercial use as long as 9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions 10 * the following conditions are aheared to. The following conditions
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 #include <stdlib.h> 60 #include <stdlib.h>
61 #include <string.h> 61 #include <string.h>
62 #include "apps.h" 62 #include "apps.h"
63 #include <openssl/bio.h> 63 #include <openssl/bio.h>
64 #include <openssl/err.h> 64 #include <openssl/err.h>
65 #include <openssl/evp.h> 65 #include <openssl/evp.h>
66 #include <openssl/objects.h> 66 #include <openssl/objects.h>
67 #include <openssl/x509.h> 67 #include <openssl/x509.h>
68 #include <openssl/rand.h> 68 #include <openssl/rand.h>
69 #include <openssl/pem.h> 69 #include <openssl/pem.h>
70 #include <openssl/comp.h>
70 #include <ctype.h> 71 #include <ctype.h>
71 72
72 int set_hex(char *in,unsigned char *out,int size); 73 int set_hex(char *in,unsigned char *out,int size);
73 #undef SIZE 74 #undef SIZE
74 #undef BSIZE 75 #undef BSIZE
75 #undef PROG 76 #undef PROG
76 77
77 #define SIZE (512) 78 #define SIZE (512)
78 #define BSIZE (8*1024) 79 #define BSIZE (8*1024)
79 #define PROG enc_main 80 #define PROG enc_main
(...skipping 13 matching lines...) Expand all
93 n=0; 94 n=0;
94 } 95 }
95 else 96 else
96 BIO_printf(bio," "); 97 BIO_printf(bio," ");
97 } 98 }
98 99
99 int MAIN(int, char **); 100 int MAIN(int, char **);
100 101
101 int MAIN(int argc, char **argv) 102 int MAIN(int argc, char **argv)
102 { 103 {
103 #ifndef OPENSSL_NO_ENGINE
104 ENGINE *e = NULL;
105 #endif
106 static const char magic[]="Salted__"; 104 static const char magic[]="Salted__";
107 char mbuf[sizeof magic-1]; 105 char mbuf[sizeof magic-1];
108 char *strbuf=NULL; 106 char *strbuf=NULL;
109 unsigned char *buff=NULL,*bufsize=NULL; 107 unsigned char *buff=NULL,*bufsize=NULL;
110 int bsize=BSIZE,verbose=0; 108 int bsize=BSIZE,verbose=0;
111 int ret=1,inl; 109 int ret=1,inl;
112 int nopad = 0; 110 int nopad = 0;
113 unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH]; 111 unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
114 unsigned char salt[PKCS5_SALT_LEN]; 112 unsigned char salt[PKCS5_SALT_LEN];
115 char *str=NULL, *passarg = NULL, *pass = NULL; 113 char *str=NULL, *passarg = NULL, *pass = NULL;
116 char *hkey=NULL,*hiv=NULL,*hsalt = NULL; 114 char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
117 char *md=NULL; 115 char *md=NULL;
118 int enc=1,printkey=0,i,base64=0; 116 int enc=1,printkey=0,i,base64=0;
117 #ifdef ZLIB
118 int do_zlib=0;
119 BIO *bzl = NULL;
120 #endif
119 int debug=0,olb64=0,nosalt=0; 121 int debug=0,olb64=0,nosalt=0;
120 const EVP_CIPHER *cipher=NULL,*c; 122 const EVP_CIPHER *cipher=NULL,*c;
121 EVP_CIPHER_CTX *ctx = NULL; 123 EVP_CIPHER_CTX *ctx = NULL;
122 char *inf=NULL,*outf=NULL; 124 char *inf=NULL,*outf=NULL;
123 BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL; 125 BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL;
124 #define PROG_NAME_SIZE 39 126 #define PROG_NAME_SIZE 39
125 char pname[PROG_NAME_SIZE+1]; 127 char pname[PROG_NAME_SIZE+1];
126 #ifndef OPENSSL_NO_ENGINE 128 #ifndef OPENSSL_NO_ENGINE
127 char *engine = NULL; 129 char *engine = NULL;
128 #endif 130 #endif
129 const EVP_MD *dgst=NULL; 131 const EVP_MD *dgst=NULL;
130 int non_fips_allow = 0;
131 132
132 apps_startup(); 133 apps_startup();
133 134
134 if (bio_err == NULL) 135 if (bio_err == NULL)
135 if ((bio_err=BIO_new(BIO_s_file())) != NULL) 136 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
136 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 137 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
137 138
138 if (!load_config(bio_err, NULL)) 139 if (!load_config(bio_err, NULL))
139 goto end; 140 goto end;
140 141
141 /* first check the program name */ 142 /* first check the program name */
142 program_name(argv[0],pname,sizeof pname); 143 program_name(argv[0],pname,sizeof pname);
143 if (strcmp(pname,"base64") == 0) 144 if (strcmp(pname,"base64") == 0)
144 base64=1; 145 base64=1;
146 #ifdef ZLIB
147 if (strcmp(pname,"zlib") == 0)
148 do_zlib=1;
149 #endif
145 150
146 cipher=EVP_get_cipherbyname(pname); 151 cipher=EVP_get_cipherbyname(pname);
152 #ifdef ZLIB
153 if (!do_zlib && !base64 && (cipher == NULL)
154 && (strcmp(pname,"enc") != 0))
155 #else
147 if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0)) 156 if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0))
157 #endif
148 { 158 {
149 BIO_printf(bio_err,"%s is an unknown cipher\n",pname); 159 BIO_printf(bio_err,"%s is an unknown cipher\n",pname);
150 goto bad; 160 goto bad;
151 } 161 }
152 162
153 argc--; 163 argc--;
154 argv++; 164 argv++;
155 while (argc >= 1) 165 while (argc >= 1)
156 { 166 {
157 if (strcmp(*argv,"-e") == 0) 167 if (strcmp(*argv,"-e") == 0)
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 else if (strcmp(*argv,"-debug") == 0) 203 else if (strcmp(*argv,"-debug") == 0)
194 debug=1; 204 debug=1;
195 else if (strcmp(*argv,"-P") == 0) 205 else if (strcmp(*argv,"-P") == 0)
196 printkey=2; 206 printkey=2;
197 else if (strcmp(*argv,"-A") == 0) 207 else if (strcmp(*argv,"-A") == 0)
198 olb64=1; 208 olb64=1;
199 else if (strcmp(*argv,"-a") == 0) 209 else if (strcmp(*argv,"-a") == 0)
200 base64=1; 210 base64=1;
201 else if (strcmp(*argv,"-base64") == 0) 211 else if (strcmp(*argv,"-base64") == 0)
202 base64=1; 212 base64=1;
213 #ifdef ZLIB
214 else if (strcmp(*argv,"-z") == 0)
215 do_zlib=1;
216 #endif
203 else if (strcmp(*argv,"-bufsize") == 0) 217 else if (strcmp(*argv,"-bufsize") == 0)
204 { 218 {
205 if (--argc < 1) goto bad; 219 if (--argc < 1) goto bad;
206 bufsize=(unsigned char *)*(++argv); 220 bufsize=(unsigned char *)*(++argv);
207 } 221 }
208 else if (strcmp(*argv,"-k") == 0) 222 else if (strcmp(*argv,"-k") == 0)
209 { 223 {
210 if (--argc < 1) goto bad; 224 if (--argc < 1) goto bad;
211 str= *(++argv); 225 str= *(++argv);
212 } 226 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 else if (strcmp(*argv,"-iv") == 0) 274 else if (strcmp(*argv,"-iv") == 0)
261 { 275 {
262 if (--argc < 1) goto bad; 276 if (--argc < 1) goto bad;
263 hiv= *(++argv); 277 hiv= *(++argv);
264 } 278 }
265 else if (strcmp(*argv,"-md") == 0) 279 else if (strcmp(*argv,"-md") == 0)
266 { 280 {
267 if (--argc < 1) goto bad; 281 if (--argc < 1) goto bad;
268 md= *(++argv); 282 md= *(++argv);
269 } 283 }
270 else if (strcmp(*argv,"-non-fips-allow") == 0)
271 non_fips_allow = 1;
272 else if ((argv[0][0] == '-') && 284 else if ((argv[0][0] == '-') &&
273 ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL)) 285 ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL))
274 { 286 {
275 cipher=c; 287 cipher=c;
276 } 288 }
277 else if (strcmp(*argv,"-none") == 0) 289 else if (strcmp(*argv,"-none") == 0)
278 cipher=NULL; 290 cipher=NULL;
279 else 291 else
280 { 292 {
281 BIO_printf(bio_err,"unknown option '%s'\n",*argv); 293 BIO_printf(bio_err,"unknown option '%s'\n",*argv);
282 bad: 294 bad:
283 BIO_printf(bio_err,"options are\n"); 295 BIO_printf(bio_err,"options are\n");
284 BIO_printf(bio_err,"%-14s input file\n","-in <file>"); 296 BIO_printf(bio_err,"%-14s input file\n","-in <file>");
285 BIO_printf(bio_err,"%-14s output file\n","-out <file>"); 297 BIO_printf(bio_err,"%-14s output file\n","-out <file>");
286 BIO_printf(bio_err,"%-14s pass phrase source\n","-pass < arg>"); 298 BIO_printf(bio_err,"%-14s pass phrase source\n","-pass < arg>");
287 BIO_printf(bio_err,"%-14s encrypt\n","-e"); 299 BIO_printf(bio_err,"%-14s encrypt\n","-e");
288 BIO_printf(bio_err,"%-14s decrypt\n","-d"); 300 BIO_printf(bio_err,"%-14s decrypt\n","-d");
289 BIO_printf(bio_err,"%-14s base64 encode/decode, dependin g on encryption flag\n","-a/-base64"); 301 BIO_printf(bio_err,"%-14s base64 encode/decode, dependin g on encryption flag\n","-a/-base64");
290 BIO_printf(bio_err,"%-14s passphrase is the next argumen t\n","-k"); 302 BIO_printf(bio_err,"%-14s passphrase is the next argumen t\n","-k");
291 BIO_printf(bio_err,"%-14s passphrase is the first line o f the file argument\n","-kfile"); 303 BIO_printf(bio_err,"%-14s passphrase is the first line o f the file argument\n","-kfile");
292 BIO_printf(bio_err,"%-14s the next argument is the md to use to create a key\n","-md"); 304 BIO_printf(bio_err,"%-14s the next argument is the md to use to create a key\n","-md");
293 BIO_printf(bio_err,"%-14s from a passphrase. One of m d2, md5, sha or sha1\n",""); 305 BIO_printf(bio_err,"%-14s from a passphrase. One of m d2, md5, sha or sha1\n","");
306 BIO_printf(bio_err,"%-14s salt in hex is the next argume nt\n","-S");
294 BIO_printf(bio_err,"%-14s key/iv in hex is the next argu ment\n","-K/-iv"); 307 BIO_printf(bio_err,"%-14s key/iv in hex is the next argu ment\n","-K/-iv");
295 BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]"); 308 BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]");
296 BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>") ; 309 BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>") ;
310 BIO_printf(bio_err,"%-14s disable standard block padding \n","-nopad");
297 #ifndef OPENSSL_NO_ENGINE 311 #ifndef OPENSSL_NO_ENGINE
298 BIO_printf(bio_err,"%-14s use engine e, possibly a hardw are device.\n","-engine e"); 312 BIO_printf(bio_err,"%-14s use engine e, possibly a hardw are device.\n","-engine e");
299 #endif 313 #endif
300 314
301 BIO_printf(bio_err,"Cipher Types\n"); 315 BIO_printf(bio_err,"Cipher Types\n");
302 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, 316 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
303 show_ciphers, 317 show_ciphers,
304 bio_err); 318 bio_err);
305 BIO_printf(bio_err,"\n"); 319 BIO_printf(bio_err,"\n");
306 320
307 goto end; 321 goto end;
308 } 322 }
309 argc--; 323 argc--;
310 argv++; 324 argv++;
311 } 325 }
312 326
313 #ifndef OPENSSL_NO_ENGINE 327 #ifndef OPENSSL_NO_ENGINE
314 e = setup_engine(bio_err, engine, 0); 328 setup_engine(bio_err, engine, 0);
315 #endif 329 #endif
316 330
317 if (md && (dgst=EVP_get_digestbyname(md)) == NULL) 331 if (md && (dgst=EVP_get_digestbyname(md)) == NULL)
318 { 332 {
319 BIO_printf(bio_err,"%s is an unsupported message digest type\n", md); 333 BIO_printf(bio_err,"%s is an unsupported message digest type\n", md);
320 goto end; 334 goto end;
321 } 335 }
322 336
323 if (dgst == NULL) 337 if (dgst == NULL)
324 { 338 {
325 » » if (in_FIPS_mode) 339 » » dgst = EVP_md5();
326 » » » dgst = EVP_sha1();
327 » » else
328 » » » dgst = EVP_md5();
329 } 340 }
330 341
331 if (bufsize != NULL) 342 if (bufsize != NULL)
332 { 343 {
333 unsigned long n; 344 unsigned long n;
334 345
335 for (n=0; *bufsize; bufsize++) 346 for (n=0; *bufsize; bufsize++)
336 { 347 {
337 i= *bufsize; 348 i= *bufsize;
338 if ((i <= '9') && (i >= '0')) 349 if ((i <= '9') && (i >= '0'))
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 if (debug) 386 if (debug)
376 { 387 {
377 BIO_set_callback(in,BIO_debug_callback); 388 BIO_set_callback(in,BIO_debug_callback);
378 BIO_set_callback(out,BIO_debug_callback); 389 BIO_set_callback(out,BIO_debug_callback);
379 BIO_set_callback_arg(in,(char *)bio_err); 390 BIO_set_callback_arg(in,(char *)bio_err);
380 BIO_set_callback_arg(out,(char *)bio_err); 391 BIO_set_callback_arg(out,(char *)bio_err);
381 } 392 }
382 393
383 if (inf == NULL) 394 if (inf == NULL)
384 { 395 {
396 #ifndef OPENSSL_NO_SETVBUF_IONBF
385 if (bufsize != NULL) 397 if (bufsize != NULL)
386 setvbuf(stdin, (char *)NULL, _IONBF, 0); 398 setvbuf(stdin, (char *)NULL, _IONBF, 0);
399 #endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
387 BIO_set_fp(in,stdin,BIO_NOCLOSE); 400 BIO_set_fp(in,stdin,BIO_NOCLOSE);
388 } 401 }
389 else 402 else
390 { 403 {
391 if (BIO_read_filename(in,inf) <= 0) 404 if (BIO_read_filename(in,inf) <= 0)
392 { 405 {
393 perror(inf); 406 perror(inf);
394 goto end; 407 goto end;
395 } 408 }
396 } 409 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 BIO_printf(bio_err,"bad password read\n"); 442 BIO_printf(bio_err,"bad password read\n");
430 goto end; 443 goto end;
431 } 444 }
432 } 445 }
433 } 446 }
434 447
435 448
436 if (outf == NULL) 449 if (outf == NULL)
437 { 450 {
438 BIO_set_fp(out,stdout,BIO_NOCLOSE); 451 BIO_set_fp(out,stdout,BIO_NOCLOSE);
452 #ifndef OPENSSL_NO_SETVBUF_IONBF
439 if (bufsize != NULL) 453 if (bufsize != NULL)
440 setvbuf(stdout, (char *)NULL, _IONBF, 0); 454 setvbuf(stdout, (char *)NULL, _IONBF, 0);
455 #endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
441 #ifdef OPENSSL_SYS_VMS 456 #ifdef OPENSSL_SYS_VMS
442 { 457 {
443 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 458 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
444 out = BIO_push(tmpbio, out); 459 out = BIO_push(tmpbio, out);
445 } 460 }
446 #endif 461 #endif
447 } 462 }
448 else 463 else
449 { 464 {
450 if (BIO_write_filename(out,outf) <= 0) 465 if (BIO_write_filename(out,outf) <= 0)
451 { 466 {
452 perror(outf); 467 perror(outf);
453 goto end; 468 goto end;
454 } 469 }
455 } 470 }
456 471
457 rbio=in; 472 rbio=in;
458 wbio=out; 473 wbio=out;
459 474
475 #ifdef ZLIB
476
477 if (do_zlib)
478 {
479 if ((bzl=BIO_new(BIO_f_zlib())) == NULL)
480 goto end;
481 if (enc)
482 wbio=BIO_push(bzl,wbio);
483 else
484 rbio=BIO_push(bzl,rbio);
485 }
486 #endif
487
460 if (base64) 488 if (base64)
461 { 489 {
462 if ((b64=BIO_new(BIO_f_base64())) == NULL) 490 if ((b64=BIO_new(BIO_f_base64())) == NULL)
463 goto end; 491 goto end;
464 if (debug) 492 if (debug)
465 { 493 {
466 BIO_set_callback(b64,BIO_debug_callback); 494 BIO_set_callback(b64,BIO_debug_callback);
467 BIO_set_callback_arg(b64,(char *)bio_err); 495 BIO_set_callback_arg(b64,(char *)bio_err);
468 } 496 }
469 if (olb64) 497 if (olb64)
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 } 582 }
555 583
556 if ((benc=BIO_new(BIO_f_cipher())) == NULL) 584 if ((benc=BIO_new(BIO_f_cipher())) == NULL)
557 goto end; 585 goto end;
558 586
559 /* Since we may be changing parameters work on the encryption 587 /* Since we may be changing parameters work on the encryption
560 * context rather than calling BIO_set_cipher(). 588 * context rather than calling BIO_set_cipher().
561 */ 589 */
562 590
563 BIO_get_cipher_ctx(benc, &ctx); 591 BIO_get_cipher_ctx(benc, &ctx);
564
565 if (non_fips_allow)
566 EVP_CIPHER_CTX_set_flags(ctx,
567 EVP_CIPH_FLAG_NON_FIPS_ALLOW);
568
569 if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) 592 if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc))
570 { 593 {
571 BIO_printf(bio_err, "Error setting cipher %s\n", 594 BIO_printf(bio_err, "Error setting cipher %s\n",
572 EVP_CIPHER_name(cipher)); 595 EVP_CIPHER_name(cipher));
573 ERR_print_errors(bio_err); 596 ERR_print_errors(bio_err);
574 goto end; 597 goto end;
575 } 598 }
576 599
577 if (nopad) 600 if (nopad)
578 EVP_CIPHER_CTX_set_padding(ctx, 0); 601 EVP_CIPHER_CTX_set_padding(ctx, 0);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out )); 672 BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out ));
650 } 673 }
651 end: 674 end:
652 ERR_print_errors(bio_err); 675 ERR_print_errors(bio_err);
653 if (strbuf != NULL) OPENSSL_free(strbuf); 676 if (strbuf != NULL) OPENSSL_free(strbuf);
654 if (buff != NULL) OPENSSL_free(buff); 677 if (buff != NULL) OPENSSL_free(buff);
655 if (in != NULL) BIO_free(in); 678 if (in != NULL) BIO_free(in);
656 if (out != NULL) BIO_free_all(out); 679 if (out != NULL) BIO_free_all(out);
657 if (benc != NULL) BIO_free(benc); 680 if (benc != NULL) BIO_free(benc);
658 if (b64 != NULL) BIO_free(b64); 681 if (b64 != NULL) BIO_free(b64);
682 #ifdef ZLIB
683 if (bzl != NULL) BIO_free(bzl);
684 #endif
659 if(pass) OPENSSL_free(pass); 685 if(pass) OPENSSL_free(pass);
660 apps_shutdown(); 686 apps_shutdown();
661 OPENSSL_EXIT(ret); 687 OPENSSL_EXIT(ret);
662 } 688 }
663 689
664 int set_hex(char *in, unsigned char *out, int size) 690 int set_hex(char *in, unsigned char *out, int size)
665 { 691 {
666 int i,n; 692 int i,n;
667 unsigned char j; 693 unsigned char j;
668 694
(...skipping 20 matching lines...) Expand all
689 BIO_printf(bio_err,"non-hex digit\n"); 715 BIO_printf(bio_err,"non-hex digit\n");
690 return(0); 716 return(0);
691 } 717 }
692 if (i&1) 718 if (i&1)
693 out[i/2]|=j; 719 out[i/2]|=j;
694 else 720 else
695 out[i/2]=(j<<4); 721 out[i/2]=(j<<4);
696 } 722 }
697 return(1); 723 return(1);
698 } 724 }
OLDNEW
« no previous file with comments | « openssl/apps/ecparam.c ('k') | openssl/apps/engine.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698