Message ID | 20170817141546.31426-1-christian.storm@siemens.com |
---|---|
State | Accepted |
Delegated to: | Stefano Babic |
Headers | show |
On 17/08/2017 16:15, Christian Storm wrote: > Support OpenSSL symmetric image encryption using salt. For backwards > compatibility, also support symmetric image encryption without salt. > > Signed-off-by: Christian Storm <christian.storm@siemens.com> > --- > core/cpio_utils.c | 4 +++- > core/util.c | 53 ++++++++++++++++++++++++++++++++--------- > corelib/swupdate_decrypt.c | 20 ++++++++++++++-- > doc/source/encrypted_images.rst | 28 ++++++++++++++-------- > include/sslapi.h | 4 ++-- > include/util.h | 1 + > 6 files changed, 84 insertions(+), 26 deletions(-) > > diff --git a/core/cpio_utils.c b/core/cpio_utils.c > index 7834a89..c3df86f 100644 > --- a/core/cpio_utils.c > +++ b/core/cpio_utils.c > @@ -130,6 +130,7 @@ int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi > unsigned int md_len = 0; > unsigned char *aes_key; > unsigned char *ivt; > + unsigned char *salt; > > if (!callback) { > callback = copy_write; > @@ -166,7 +167,8 @@ int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi > > aes_key = get_aes_key(); > ivt = get_aes_ivt(); > - dcrypt = swupdate_DECRYPT_init(aes_key, ivt); > + salt = get_aes_salt(); > + dcrypt = swupdate_DECRYPT_init(aes_key, ivt, salt); > if (!dcrypt) { > ERROR("decrypt initialization failure, aborting"); > ret = -EFAULT; > diff --git a/core/util.c b/core/util.c > index fc8e282..b714f29 100644 > --- a/core/util.c > +++ b/core/util.c > @@ -31,9 +31,15 @@ > #include "util.h" > #include "generated/autoconf.h" > > +/* > + * key is 256 bit for aes_256 > + * ivt is 128 bit > + * salt is 64 bit > + */ > struct decryption_key { > unsigned char key[32]; > unsigned char ivt[16]; > + unsigned char salt[8]; > }; > > static struct decryption_key *aes_key = NULL; > @@ -276,6 +282,10 @@ static int ascii_to_bin(unsigned char *hash, const char *s, size_t len) > unsigned int i; > unsigned int val; > > + if (s == NULL) { > + return 0; > + } > + > if (len % 2) > return -EINVAL; > if (strlen(s) == len) { > @@ -339,14 +349,29 @@ int count_elem_list(struct imglist *list) > int load_decryption_key(char *fname) > { > FILE *fp; > - char *b1, *b2; > + char *b1 = NULL, *b2 = NULL, *b3 = NULL; > int ret; > > fp = fopen(fname, "r"); > if (!fp) > return -EBADF; > > - ret = fscanf(fp, "%ms %ms", &b1, &b2); > + ret = fscanf(fp, "%ms %ms %ms", &b1, &b2, &b3); > + switch (ret) { > + case 2: > + b3 = NULL; > + DEBUG("Read decryption key and initialization vector from file %s.", fname); > + break; > + case 3: > + DEBUG("Read decryption key, initialization vector, and salt from file %s.", fname); > + break; > + default: > + if (b1 != NULL) > + free(b1); > + fprintf(stderr, "File with decryption key is not in the format <key> <ivt> nor <key> <ivt> <salt>\n"); > + fclose(fp); > + return -EINVAL; > + } > fclose(fp); > > if (aes_key) > @@ -356,16 +381,16 @@ int load_decryption_key(char *fname) > if (!aes_key) > return -ENOMEM; > > - if (ret != 2) { > - fprintf(stderr, "File with decryption key is in the format <key> <ivt>\n"); > - return -EINVAL; > - } > + ret = ascii_to_bin(aes_key->key, b1, sizeof(aes_key->key) * 2) | > + ascii_to_bin(aes_key->ivt, b2, sizeof(aes_key->ivt) * 2) | > + ascii_to_bin(aes_key->salt, b3, sizeof(aes_key->salt) * 2); > > - /* > - * Key is for aes_256, it must be 256 bit > - * and IVT is 128 bit > - */ > - ret = ascii_to_bin(aes_key->key, b1, 64) | ascii_to_bin(aes_key->ivt, b2, 32); > + if (b1 != NULL) > + free(b1); > + if (b2 != NULL) > + free(b2); > + if (b3 != NULL) > + free(b3); > > if (ret) { > fprintf(stderr, "Keys are invalid\n"); > @@ -387,6 +412,12 @@ unsigned char *get_aes_ivt(void) { > return aes_key->ivt; > } > > +unsigned char *get_aes_salt(void) { > + if (!aes_key) > + return NULL; > + return aes_key->salt; > +} > + > char** string_split(char* s, const char d) > { > char** result = 0; > diff --git a/corelib/swupdate_decrypt.c b/corelib/swupdate_decrypt.c > index 8e092c8..24a6c5c 100644 > --- a/corelib/swupdate_decrypt.c > +++ b/corelib/swupdate_decrypt.c > @@ -28,7 +28,7 @@ > #include "sslapi.h" > #include "util.h" > > -struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv) > +struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv, unsigned char *salt) > { > struct swupdate_digest *dgst; > int ret; > @@ -38,11 +38,27 @@ struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char > return NULL; > } > > + const EVP_CIPHER *cipher = EVP_aes_256_cbc(); > + > dgst = calloc(1, sizeof(*dgst)); > if (!dgst) { > return NULL; > } > > + if (salt != NULL) { > + unsigned char dummy_key[EVP_MAX_KEY_LENGTH]; > + unsigned char dummy_iv[EVP_MAX_IV_LENGTH]; > + unsigned char dummy_pwd[5] = "DUMMY"; > + if (!EVP_BytesToKey(cipher, EVP_sha1(), salt, > + dummy_pwd, sizeof(dummy_pwd), > + 1, > + (unsigned char *)&dummy_key, (unsigned char *)&dummy_iv)) { > + ERROR("Cannot set salt."); > + free(dgst); > + return NULL; > + } > + } > + > #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) > EVP_CIPHER_CTX_init(&dgst->ctxdec); > #else > @@ -63,7 +79,7 @@ struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char > /* > * Check openSSL documentation for return errors > */ > - ret = EVP_DecryptInit_ex(SSL_GET_CTXDEC(dgst), EVP_aes_256_cbc(), NULL, key, iv); > + ret = EVP_DecryptInit_ex(SSL_GET_CTXDEC(dgst), cipher, NULL, key, iv); > if (ret != 1) { > ERROR("Decrypt Engine not initialized, error 0x%lx\n", ERR_get_error()); > free(dgst); > diff --git a/doc/source/encrypted_images.rst b/doc/source/encrypted_images.rst > index 4358126..a7d85a2 100644 > --- a/doc/source/encrypted_images.rst > +++ b/doc/source/encrypted_images.rst > @@ -14,35 +14,43 @@ A complete documentation can be found at the > > :: > > - openssl enc -aes-256-cbc -k <PASSPHRASE> -nosalt -P -md sha1 > + openssl enc -aes-256-cbc -k <PASSPHRASE> -P -md sha1 > > The key and initialization vector is generated based on the given ``<PASSPHRASE>``. > The output of the above command looks like this: > > :: > > - key=B60D121B438A380C343D5EC3C2037564B82FFEF3542808AB5694FA93C3179140 > - iv =20578C4FEF1AEE907B1DC95C776F8160 > - > + salt=CE7B0488EFBF0D1B > + key=B78CC67DD3DC13042A1B575184D4E16D6A09412C242CE253ACEE0F06B5AD68FC > + iv =65D793B87B6724BB27954C7664F15FF3 > > Then, encrypt an image using this information via > > :: > > - openssl enc -aes-256-cbc -in <INFILE> -out <OUTFILE> -K <KEY> -iv <IV> > + openssl enc -aes-256-cbc -in <INFILE> -out <OUTFILE> -K <KEY> -iv <IV> -S <SALT> > > where ``<INFILE>`` is the unencrypted source image file and ``<OUTFILE>`` is the > encrypted output image file to be referenced in ``sw-description``. > -``<KEY>`` is the hex value part of the first line of output from the key generation > -command above and ``<IV>`` is the hex value part of the second line. > +``<KEY>`` is the hex value part of the 2nd line of output from the key generation > +command above, ``<IV>`` is the hex value part of the 3rd line, and ``<SALT>`` is > +the hex value part of the 1st line. > > Then, create a key file to be supplied to SWUpdate via the `-K` switch by > -putting the key and initialization vector hex values on one line separated by > -whitespace, e.g., for above example values > +putting the key, initialization vector, and salt hex values on one line > +separated by whitespace, e.g., for above example values > > :: > > - B60D121B438A380C343D5EC3C2037564B82FFEF3542808AB5694FA93C3179140 20578C4FEF1AEE907B1DC95C776F8160 > + B78CC67DD3DC13042A1B575184D4E16D6A09412C242CE253ACEE0F06B5AD68FC 65D793B87B6724BB27954C7664F15FF3 CE7B0488EFBF0D1B > + > + > +Note that, while not recommended and for backwards compatibility, OpenSSL may be > +used without salt. For disabling salt, add the ``-nosalt`` parameter to the key > +generation command above. Accordingly, drop the ``-S <SALT>`` parameter in the > +encryption command and omit the 3rd field of the key file to be supplied to > +SWUpdate being the salt. > > > Example sw-description with Encrypted Image > diff --git a/include/sslapi.h b/include/sslapi.h > index 500db7c..1df656d 100644 > --- a/include/sslapi.h > +++ b/include/sslapi.h > @@ -106,7 +106,7 @@ int swupdate_HASH_compare(unsigned char *hash1, unsigned char *hash2); > #endif > > #ifdef CONFIG_ENCRYPTED_IMAGES > -struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv); > +struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv, unsigned char *salt); > int swupdate_DECRYPT_update(struct swupdate_digest *dgst, unsigned char *buf, > int *outlen, unsigned char *cryptbuf, int inlen); > int swupdate_DECRYPT_final(struct swupdate_digest *dgst, unsigned char *buf, > @@ -117,7 +117,7 @@ void swupdate_DECRYPT_cleanup(struct swupdate_digest *dgst); > * Note: macro for swupdate_DECRYPT_init is > * just to avoid compiler warnings > */ > -#define swupdate_DECRYPT_init(key, iv) (((key != NULL) | (ivt != NULL)) ? NULL : NULL) > +#define swupdate_DECRYPT_init(key, iv, salt) (((key != NULL) | (ivt != NULL) | (salt != NULL)) ? NULL : NULL) > #define swupdate_DECRYPT_update(p, buf, len, cbuf, inlen) (-1) > #define swupdate_DECRYPT_final(p, buf, len) (-1) > #define swupdate_DECRYPT_cleanup(p) > diff --git a/include/util.h b/include/util.h > index 2d6f047..70a0acc 100644 > --- a/include/util.h > +++ b/include/util.h > @@ -173,6 +173,7 @@ int count_elem_list(struct imglist *list); > int load_decryption_key(char *fname); > unsigned char *get_aes_key(void); > unsigned char *get_aes_ivt(void); > +unsigned char *get_aes_salt(void); > > /* Getting global information */ > int get_install_info(sourcetype *source, char *buf, size_t len); > Applied to -master, thanks ! Best regards, Stefano Babic
diff --git a/core/cpio_utils.c b/core/cpio_utils.c index 7834a89..c3df86f 100644 --- a/core/cpio_utils.c +++ b/core/cpio_utils.c @@ -130,6 +130,7 @@ int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi unsigned int md_len = 0; unsigned char *aes_key; unsigned char *ivt; + unsigned char *salt; if (!callback) { callback = copy_write; @@ -166,7 +167,8 @@ int copyfile(int fdin, void *out, unsigned int nbytes, unsigned long *offs, unsi aes_key = get_aes_key(); ivt = get_aes_ivt(); - dcrypt = swupdate_DECRYPT_init(aes_key, ivt); + salt = get_aes_salt(); + dcrypt = swupdate_DECRYPT_init(aes_key, ivt, salt); if (!dcrypt) { ERROR("decrypt initialization failure, aborting"); ret = -EFAULT; diff --git a/core/util.c b/core/util.c index fc8e282..b714f29 100644 --- a/core/util.c +++ b/core/util.c @@ -31,9 +31,15 @@ #include "util.h" #include "generated/autoconf.h" +/* + * key is 256 bit for aes_256 + * ivt is 128 bit + * salt is 64 bit + */ struct decryption_key { unsigned char key[32]; unsigned char ivt[16]; + unsigned char salt[8]; }; static struct decryption_key *aes_key = NULL; @@ -276,6 +282,10 @@ static int ascii_to_bin(unsigned char *hash, const char *s, size_t len) unsigned int i; unsigned int val; + if (s == NULL) { + return 0; + } + if (len % 2) return -EINVAL; if (strlen(s) == len) { @@ -339,14 +349,29 @@ int count_elem_list(struct imglist *list) int load_decryption_key(char *fname) { FILE *fp; - char *b1, *b2; + char *b1 = NULL, *b2 = NULL, *b3 = NULL; int ret; fp = fopen(fname, "r"); if (!fp) return -EBADF; - ret = fscanf(fp, "%ms %ms", &b1, &b2); + ret = fscanf(fp, "%ms %ms %ms", &b1, &b2, &b3); + switch (ret) { + case 2: + b3 = NULL; + DEBUG("Read decryption key and initialization vector from file %s.", fname); + break; + case 3: + DEBUG("Read decryption key, initialization vector, and salt from file %s.", fname); + break; + default: + if (b1 != NULL) + free(b1); + fprintf(stderr, "File with decryption key is not in the format <key> <ivt> nor <key> <ivt> <salt>\n"); + fclose(fp); + return -EINVAL; + } fclose(fp); if (aes_key) @@ -356,16 +381,16 @@ int load_decryption_key(char *fname) if (!aes_key) return -ENOMEM; - if (ret != 2) { - fprintf(stderr, "File with decryption key is in the format <key> <ivt>\n"); - return -EINVAL; - } + ret = ascii_to_bin(aes_key->key, b1, sizeof(aes_key->key) * 2) | + ascii_to_bin(aes_key->ivt, b2, sizeof(aes_key->ivt) * 2) | + ascii_to_bin(aes_key->salt, b3, sizeof(aes_key->salt) * 2); - /* - * Key is for aes_256, it must be 256 bit - * and IVT is 128 bit - */ - ret = ascii_to_bin(aes_key->key, b1, 64) | ascii_to_bin(aes_key->ivt, b2, 32); + if (b1 != NULL) + free(b1); + if (b2 != NULL) + free(b2); + if (b3 != NULL) + free(b3); if (ret) { fprintf(stderr, "Keys are invalid\n"); @@ -387,6 +412,12 @@ unsigned char *get_aes_ivt(void) { return aes_key->ivt; } +unsigned char *get_aes_salt(void) { + if (!aes_key) + return NULL; + return aes_key->salt; +} + char** string_split(char* s, const char d) { char** result = 0; diff --git a/corelib/swupdate_decrypt.c b/corelib/swupdate_decrypt.c index 8e092c8..24a6c5c 100644 --- a/corelib/swupdate_decrypt.c +++ b/corelib/swupdate_decrypt.c @@ -28,7 +28,7 @@ #include "sslapi.h" #include "util.h" -struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv) +struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv, unsigned char *salt) { struct swupdate_digest *dgst; int ret; @@ -38,11 +38,27 @@ struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char return NULL; } + const EVP_CIPHER *cipher = EVP_aes_256_cbc(); + dgst = calloc(1, sizeof(*dgst)); if (!dgst) { return NULL; } + if (salt != NULL) { + unsigned char dummy_key[EVP_MAX_KEY_LENGTH]; + unsigned char dummy_iv[EVP_MAX_IV_LENGTH]; + unsigned char dummy_pwd[5] = "DUMMY"; + if (!EVP_BytesToKey(cipher, EVP_sha1(), salt, + dummy_pwd, sizeof(dummy_pwd), + 1, + (unsigned char *)&dummy_key, (unsigned char *)&dummy_iv)) { + ERROR("Cannot set salt."); + free(dgst); + return NULL; + } + } + #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) EVP_CIPHER_CTX_init(&dgst->ctxdec); #else @@ -63,7 +79,7 @@ struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char /* * Check openSSL documentation for return errors */ - ret = EVP_DecryptInit_ex(SSL_GET_CTXDEC(dgst), EVP_aes_256_cbc(), NULL, key, iv); + ret = EVP_DecryptInit_ex(SSL_GET_CTXDEC(dgst), cipher, NULL, key, iv); if (ret != 1) { ERROR("Decrypt Engine not initialized, error 0x%lx\n", ERR_get_error()); free(dgst); diff --git a/doc/source/encrypted_images.rst b/doc/source/encrypted_images.rst index 4358126..a7d85a2 100644 --- a/doc/source/encrypted_images.rst +++ b/doc/source/encrypted_images.rst @@ -14,35 +14,43 @@ A complete documentation can be found at the :: - openssl enc -aes-256-cbc -k <PASSPHRASE> -nosalt -P -md sha1 + openssl enc -aes-256-cbc -k <PASSPHRASE> -P -md sha1 The key and initialization vector is generated based on the given ``<PASSPHRASE>``. The output of the above command looks like this: :: - key=B60D121B438A380C343D5EC3C2037564B82FFEF3542808AB5694FA93C3179140 - iv =20578C4FEF1AEE907B1DC95C776F8160 - + salt=CE7B0488EFBF0D1B + key=B78CC67DD3DC13042A1B575184D4E16D6A09412C242CE253ACEE0F06B5AD68FC + iv =65D793B87B6724BB27954C7664F15FF3 Then, encrypt an image using this information via :: - openssl enc -aes-256-cbc -in <INFILE> -out <OUTFILE> -K <KEY> -iv <IV> + openssl enc -aes-256-cbc -in <INFILE> -out <OUTFILE> -K <KEY> -iv <IV> -S <SALT> where ``<INFILE>`` is the unencrypted source image file and ``<OUTFILE>`` is the encrypted output image file to be referenced in ``sw-description``. -``<KEY>`` is the hex value part of the first line of output from the key generation -command above and ``<IV>`` is the hex value part of the second line. +``<KEY>`` is the hex value part of the 2nd line of output from the key generation +command above, ``<IV>`` is the hex value part of the 3rd line, and ``<SALT>`` is +the hex value part of the 1st line. Then, create a key file to be supplied to SWUpdate via the `-K` switch by -putting the key and initialization vector hex values on one line separated by -whitespace, e.g., for above example values +putting the key, initialization vector, and salt hex values on one line +separated by whitespace, e.g., for above example values :: - B60D121B438A380C343D5EC3C2037564B82FFEF3542808AB5694FA93C3179140 20578C4FEF1AEE907B1DC95C776F8160 + B78CC67DD3DC13042A1B575184D4E16D6A09412C242CE253ACEE0F06B5AD68FC 65D793B87B6724BB27954C7664F15FF3 CE7B0488EFBF0D1B + + +Note that, while not recommended and for backwards compatibility, OpenSSL may be +used without salt. For disabling salt, add the ``-nosalt`` parameter to the key +generation command above. Accordingly, drop the ``-S <SALT>`` parameter in the +encryption command and omit the 3rd field of the key file to be supplied to +SWUpdate being the salt. Example sw-description with Encrypted Image diff --git a/include/sslapi.h b/include/sslapi.h index 500db7c..1df656d 100644 --- a/include/sslapi.h +++ b/include/sslapi.h @@ -106,7 +106,7 @@ int swupdate_HASH_compare(unsigned char *hash1, unsigned char *hash2); #endif #ifdef CONFIG_ENCRYPTED_IMAGES -struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv); +struct swupdate_digest *swupdate_DECRYPT_init(unsigned char *key, unsigned char *iv, unsigned char *salt); int swupdate_DECRYPT_update(struct swupdate_digest *dgst, unsigned char *buf, int *outlen, unsigned char *cryptbuf, int inlen); int swupdate_DECRYPT_final(struct swupdate_digest *dgst, unsigned char *buf, @@ -117,7 +117,7 @@ void swupdate_DECRYPT_cleanup(struct swupdate_digest *dgst); * Note: macro for swupdate_DECRYPT_init is * just to avoid compiler warnings */ -#define swupdate_DECRYPT_init(key, iv) (((key != NULL) | (ivt != NULL)) ? NULL : NULL) +#define swupdate_DECRYPT_init(key, iv, salt) (((key != NULL) | (ivt != NULL) | (salt != NULL)) ? NULL : NULL) #define swupdate_DECRYPT_update(p, buf, len, cbuf, inlen) (-1) #define swupdate_DECRYPT_final(p, buf, len) (-1) #define swupdate_DECRYPT_cleanup(p) diff --git a/include/util.h b/include/util.h index 2d6f047..70a0acc 100644 --- a/include/util.h +++ b/include/util.h @@ -173,6 +173,7 @@ int count_elem_list(struct imglist *list); int load_decryption_key(char *fname); unsigned char *get_aes_key(void); unsigned char *get_aes_ivt(void); +unsigned char *get_aes_salt(void); /* Getting global information */ int get_install_info(sourcetype *source, char *buf, size_t len);
Support OpenSSL symmetric image encryption using salt. For backwards compatibility, also support symmetric image encryption without salt. Signed-off-by: Christian Storm <christian.storm@siemens.com> --- core/cpio_utils.c | 4 +++- core/util.c | 53 ++++++++++++++++++++++++++++++++--------- corelib/swupdate_decrypt.c | 20 ++++++++++++++-- doc/source/encrypted_images.rst | 28 ++++++++++++++-------- include/sslapi.h | 4 ++-- include/util.h | 1 + 6 files changed, 84 insertions(+), 26 deletions(-)