Hi, here's the next version of this patch series that aims to introduce support for LUKS2 disk encryption. The following changes have been made compared to v4:
- The JSON wrapper no verifies that jsmn tokens do not have a negative size in grub_json_getsize(), grub_json_getvalue() and grub_json_getchild(). Like this, we can detect if the jsmn library ever unexpectedly returns a negative size. - The JSON wrapper now checks for NULL pointers. - Both grub_json_getsize() and grub_json_getsize() now return an error code. The result is passed back via an out parameter. - Added a comment in the grub_json_getchild() loop that explains the weird token skipping semantics. - Redundant json object type checks in luks2.c have been removed. By now, the JSON wrapper performs type checks on calling grub_json_getchild()/grub_json_getvalue() anyway. - Stylistic cleanups. The range-diff to v4 is attached to this mail. Patrick Patrick Steinhardt (6): json: Import upstream jsmn-1.1.0 json: Implement wrapping interface bootstrap: Add gnulib's base64 module afsplitter: Move into its own module luks: Move configuration of ciphers into cryptodisk disk: Implement support for LUKS2 Makefile.util.def | 4 +- bootstrap.conf | 3 +- conf/Makefile.extra-dist | 1 + docs/grub-dev.texi | 14 + docs/grub.texi | 5 +- grub-core/Makefile.core.def | 19 +- grub-core/disk/AFSplitter.c | 3 + grub-core/disk/cryptodisk.c | 163 ++++- grub-core/disk/luks.c | 190 +---- grub-core/disk/luks2.c | 676 ++++++++++++++++++ grub-core/lib/gnulib-patches/fix-base64.patch | 23 + grub-core/lib/json/jsmn.h | 468 ++++++++++++ grub-core/lib/json/json.c | 266 +++++++ grub-core/lib/json/json.h | 105 +++ include/grub/cryptodisk.h | 3 + 15 files changed, 1763 insertions(+), 180 deletions(-) create mode 100644 grub-core/disk/luks2.c create mode 100644 grub-core/lib/gnulib-patches/fix-base64.patch create mode 100644 grub-core/lib/json/jsmn.h create mode 100644 grub-core/lib/json/json.c create mode 100644 grub-core/lib/json/json.h Range-diff against v4: 1: 2469e96f9 = 1: 2469e96f9 json: Import upstream jsmn-1.1.0 2: 126fd8408 ! 2: 1859ff982 json: Implement wrapping interface @@ grub-core/lib/json/json.c + grub_json_t *json = NULL; + jsmn_parser parser; + grub_err_t ret = GRUB_ERR_NONE; -+ int jsmn_err; ++ int jsmn_ret; + + if (!string) + return GRUB_ERR_BAD_ARGUMENT; @@ grub-core/lib/json/json.c + * Parse the string twice: first to determine how many tokens + * we need to allocate, second to fill allocated tokens. + */ -+ jsmn_init(&parser); -+ jsmn_err = jsmn_parse (&parser, string, string_len, NULL, 0); -+ if (jsmn_err <= 0) ++ jsmn_init (&parser); ++ jsmn_ret = jsmn_parse (&parser, string, string_len, NULL, 0); ++ if (jsmn_ret <= 0) + { + ret = GRUB_ERR_BAD_ARGUMENT; + goto err; + } + -+ json->tokens = grub_malloc (sizeof (jsmntok_t) * jsmn_err); ++ json->tokens = grub_malloc (sizeof (jsmntok_t) * jsmn_ret); + if (!json->tokens) + { + ret = GRUB_ERR_OUT_OF_MEMORY; @@ grub-core/lib/json/json.c + } + + jsmn_init (&parser); -+ jsmn_err = jsmn_parse (&parser, string, string_len, json->tokens, jsmn_err); -+ if (jsmn_err <= 0) ++ jsmn_ret = jsmn_parse (&parser, string, string_len, json->tokens, jsmn_ret); ++ if (jsmn_ret <= 0) + { + ret = GRUB_ERR_BAD_ARGUMENT; + goto err; @@ grub-core/lib/json/json.c + } +} + -+grub_size_t -+grub_json_getsize (const grub_json_t *json) ++grub_err_t ++grub_json_getsize (grub_size_t *out, const grub_json_t *json) +{ -+ jsmntok_t *p = &((jsmntok_t *)json->tokens)[json->idx]; ++ int size; + -+ return p->size; ++ if (!json) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ size = ((jsmntok_t *)json->tokens)[json->idx].size; ++ if (size < 0) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ *out = (size_t) size; ++ return GRUB_ERR_NONE; +} + -+grub_json_type_t -+grub_json_gettype (const grub_json_t *json) ++grub_err_t ++grub_json_gettype (grub_json_type_t *out, const grub_json_t *json) +{ -+ jsmntok_t *p = &((jsmntok_t *)json->tokens)[json->idx]; ++ if (!json) ++ return GRUB_ERR_BAD_ARGUMENT; + -+ switch (p->type) ++ switch (((jsmntok_t *)json->tokens)[json->idx].type) + { + case JSMN_OBJECT: -+ return GRUB_JSON_OBJECT; ++ *out = GRUB_JSON_OBJECT; ++ break; + case JSMN_ARRAY: -+ return GRUB_JSON_ARRAY; ++ *out = GRUB_JSON_ARRAY; ++ break; + case JSMN_STRING: -+ return GRUB_JSON_STRING; ++ *out = GRUB_JSON_STRING; ++ break; + case JSMN_PRIMITIVE: -+ return GRUB_JSON_PRIMITIVE; ++ *out = GRUB_JSON_PRIMITIVE; ++ break; + default: -+ break; ++ return GRUB_ERR_BAD_ARGUMENT; + } + -+ return GRUB_JSON_UNDEFINED; ++ return GRUB_ERR_NONE; +} + +grub_err_t -+grub_json_getchild(grub_json_t *out, const grub_json_t *parent, grub_size_t n) ++grub_json_getchild (grub_json_t *out, const grub_json_t *parent, grub_size_t n) +{ -+ jsmntok_t *p = &((jsmntok_t *)parent->tokens)[parent->idx]; -+ grub_size_t offset = 1; ++ grub_size_t offset = 1, size; ++ jsmntok_t *p; + -+ if (n >= (grub_size_t) p->size) ++ if (grub_json_getsize(&size, parent) || n >= size) + return GRUB_ERR_BAD_ARGUMENT; + ++ /* ++ * Skip the first n children. For each of the children, we need ++ * to skip their own potential children (e.g. if it's an ++ * array), as well. We thus add the children's size to n on ++ * each iteration. ++ */ ++ p = &((jsmntok_t *)parent->tokens)[parent->idx]; + while (n--) + n += p[offset++].size; + @@ grub-core/lib/json/json.c +} + +grub_err_t -+grub_json_getvalue(grub_json_t *out, const grub_json_t *parent, const char *key) ++grub_json_getvalue (grub_json_t *out, const grub_json_t *parent, const char *key) +{ -+ grub_size_t i; ++ grub_json_type_t type; ++ grub_size_t i, size; + -+ if (grub_json_gettype (parent) != GRUB_JSON_OBJECT) ++ if (grub_json_gettype (&type, parent) || type != GRUB_JSON_OBJECT) + return GRUB_ERR_BAD_ARGUMENT; + -+ for (i = 0; i < grub_json_getsize (parent); i++) ++ if (grub_json_getsize (&size, parent)) ++ return GRUB_ERR_BAD_ARGUMENT; ++ ++ for (i = 0; i < size; i++) + { + grub_json_t child; + const char *s; @@ grub-core/lib/json/json.c + grub_err_t ret; + jsmntok_t *tok; + ++ if (!parent) ++ return GRUB_ERR_BAD_ARGUMENT; ++ + if (key) + { + ret = grub_json_getvalue (&child, parent, key); @@ grub-core/lib/json/json.c + p->string[tok->end] = '\0'; + + *out_string = p->string + tok->start; -+ *out_type = grub_json_gettype (p); + -+ return GRUB_ERR_NONE; ++ return grub_json_gettype (out_type, p); +} + +grub_err_t @@ grub-core/lib/json/json.c + const char *value; + grub_err_t ret; + -+ ret = get_value(&type, &value, parent, key); ++ ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING) @@ grub-core/lib/json/json.c + const char *value; + grub_err_t ret; + -+ ret = get_value(&type, &value, parent, key); ++ ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING && type != GRUB_JSON_PRIMITIVE) @@ grub-core/lib/json/json.c + const char *value; + grub_err_t ret; + -+ ret = get_value(&type, &value, parent, key); ++ ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING && type != GRUB_JSON_PRIMITIVE) @@ grub-core/lib/json/json.h (new) + +struct grub_json +{ -+ void *tokens; -+ char *string; ++ void *tokens; ++ char *string; + grub_size_t idx; +}; +typedef struct grub_json grub_json_t; @@ grub-core/lib/json/json.h (new) + * Get the child count of the given JSON token. Children are + * present for arrays, objects (dicts) and keys of a dict. + */ -+extern grub_size_t EXPORT_FUNC(grub_json_getsize) (const grub_json_t *json); ++extern grub_err_t EXPORT_FUNC(grub_json_getsize) (grub_size_t *out, ++ const grub_json_t *json); + +/* Get the type of the given JSON token. */ -+extern grub_json_type_t EXPORT_FUNC(grub_json_gettype) (const grub_json_t *json); ++extern grub_err_t EXPORT_FUNC(grub_json_gettype) (grub_json_type_t *out, ++ const grub_json_t *json); + +/* + * Get n'th child of object, array or key. Will return an error if no 3: e29ef98a2 = 3: e3acf44c0 bootstrap: Add gnulib's base64 module 4: f95f7b1c2 = 4: 11cf3594a afsplitter: Move into its own module 5: 5a3bb8742 ! 5: 9aa067876 luks: Move configuration of ciphers into cryptodisk @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_decrypt (struct grub_cryptodisk *de + grub_cryptodisk_mode_t mode; + grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64; + int benbi_log = 0; -+ grub_err_t err = GRUB_ERR_NONE; ++ grub_err_t ret = GRUB_ERR_NONE; + + ciph = grub_crypto_lookup_cipher_by_name (ciphername); + if (!ciph) + { -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", ++ ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", + ciphername); + goto err; + } @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_decrypt (struct grub_cryptodisk *de + cipher = grub_crypto_cipher_open (ciph); + if (!cipher) + { -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s could not be initialized", ++ ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s could not be initialized", + ciphername); + goto err; + } @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_decrypt (struct grub_cryptodisk *de + secondary_cipher = grub_crypto_cipher_open (ciph); + if (!secondary_cipher) + { -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Secondary cipher %s isn't available", ++ ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Secondary cipher %s isn't available", + secondary_cipher); + goto err; + } + if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) + { -+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", + cipher->cipher->blocksize); + goto err; + } + if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) + { -+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", + secondary_cipher->cipher->blocksize); + goto err; + } @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_decrypt (struct grub_cryptodisk *de + cipheriv = ciphermode + sizeof ("lrw-") - 1; + if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) + { -+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d", ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d", + cipher->cipher->blocksize); + goto err; + } + } + else + { -+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", + ciphermode); + goto err; + } @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_decrypt (struct grub_cryptodisk *de + essiv_hash = grub_crypto_lookup_md_by_name (hash_str); + if (!essiv_hash) + { -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Couldn't load %s hash", hash_str); + goto err; + } + essiv_cipher = grub_crypto_cipher_open (ciph); + if (!essiv_cipher) + { -+ err = grub_error (GRUB_ERR_FILE_NOT_FOUND, ++ ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Couldn't load %s cipher", ciphername); + goto err; + } + } + else + { -+ err = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s", ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s", + cipheriv); + goto err; + } @@ grub-core/disk/cryptodisk.c: grub_cryptodisk_decrypt (struct grub_cryptodisk *de + crypt->essiv_hash = essiv_hash; + +err: -+ if (err) ++ if (ret) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (secondary_cipher); + } -+ return err; ++ return ret; +} + gcry_err_code_t 6: 9c21363ee ! 6: 593c1829b disk: Implement support for LUKS2 @@ grub-core/disk/luks2.c (new) + +#define LUKS_MAGIC_1ST "LUKS\xBA\xBE" +#define LUKS_MAGIC_2ND "SKUL\xBA\xBE" ++ +#define MAX_PASSPHRASE 256 + +enum grub_luks2_kdf_type @@ grub-core/disk/luks2.c (new) + grub_json_t area, af, kdf; + const char *type; + -+ if (grub_json_gettype (keyslot) != GRUB_JSON_OBJECT) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot type"); -+ + if (grub_json_getstring (&type, keyslot, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing or invalid keyslot"); + else if (grub_strcmp (type, "luks2")) @@ grub-core/disk/luks2.c (new) +{ + const char *type; + -+ if (grub_json_gettype (segment) != GRUB_JSON_OBJECT || grub_json_getstring (&type, segment, "type")) ++ if (grub_json_getstring (&type, segment, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid segment type"); + else if (grub_strcmp (type, "crypt")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported segment type %s", type); + -+ if (grub_json_getuint64 (&out->offset, segment, "offset") || ++ if (grub_json_getuint64 (&out->offset, segment, "offset") || + grub_json_getstring (&out->size, segment, "size") || + grub_json_getstring (&out->encryption, segment, "encryption") || + grub_json_getint64 (&out->sector_size, segment, "sector_size")) @@ grub-core/disk/luks2.c (new) +{ + grub_json_t segments, keyslots, o; + const char *type; -+ grub_size_t i, bit; ++ grub_size_t i, size, bit; + -+ if (grub_json_gettype (digest) != GRUB_JSON_OBJECT || grub_json_getstring (&type, digest, "type")) ++ if (grub_json_getstring (&type, digest, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest type"); + else if (grub_strcmp (type, "pbkdf2")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported digest type %s", type); @@ grub-core/disk/luks2.c (new) + grub_json_getint64 (&out->iterations, digest, "iterations")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing digest parameters"); + -+ if (grub_json_gettype (&segments) != GRUB_JSON_ARRAY) ++ if (grub_json_getsize (&size, &segments)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Digest references no segments", type); -+ if (grub_json_gettype (&keyslots) != GRUB_JSON_ARRAY) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, -+ "Digest references no keyslots", type); + -+ for (i = 0; i < grub_json_getsize (&segments); i++) ++ for (i = 0; i < size; i++) + { -+ if (grub_json_getchild(&o, &segments, i) || ++ if (grub_json_getchild (&o, &segments, i) || + grub_json_getuint64 (&bit, &o, NULL)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid segment"); + out->segments |= (1 << bit); + } + -+ for (i = 0; i < grub_json_getsize (&keyslots); i++) ++ if (grub_json_getsize (&size, &keyslots)) ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, ++ "Digest references no keyslots", type); ++ ++ for (i = 0; i < size; i++) + { -+ if (grub_json_getchild(&o, &keyslots, i) || ++ if (grub_json_getchild (&o, &keyslots, i) || + grub_json_getuint64 (&bit, &o, NULL)) -+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid segment"); ++ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot"); + out->keyslots |= (1 << bit); + } + @@ grub-core/disk/luks2.c (new) + const grub_json_t *root, grub_size_t i) +{ + grub_json_t keyslots, keyslot, digests, digest, segments, segment; -+ grub_size_t j, idx; ++ grub_size_t j, idx, size; + + /* Get nth keyslot */ + if (grub_json_getvalue (&keyslots, root, "keyslots") || @@ grub-core/disk/luks2.c (new) + + /* Get digest that matches the keyslot. */ + if (grub_json_getvalue (&digests, root, "digests") || -+ grub_json_getsize (&digests) == 0) ++ grub_json_getsize (&size, &digests)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests"); -+ for (j = 0; j < grub_json_getsize (&digests); j++) ++ for (j = 0; j < size; j++) + { + if (grub_json_getchild (&digest, &digests, i) || + grub_json_getchild (&digest, &digest, 0) || @@ grub-core/disk/luks2.c (new) + if ((d->keyslots & (1 << idx))) + break; + } -+ if (j == grub_json_getsize (&digests)) ++ if (j == size) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot %"PRIuGRUB_SIZE); + + /* Get segment that matches the digest. */ + if (grub_json_getvalue (&segments, root, "segments") || -+ grub_json_getsize (&segments) == 0) ++ grub_json_getsize (&size, &segments)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments"); -+ for (j = 0; j < grub_json_getsize (&segments); j++) ++ for (j = 0; j < size; j++) + { + if (grub_json_getchild (&segment, &segments, i) || + grub_json_getuint64 (&idx, &segment, NULL) || @@ grub-core/disk/luks2.c (new) + if ((d->segments & (1 << idx))) + break; + } -+ if (j == grub_json_getsize (&segments)) ++ if (j == size) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest %"PRIuGRUB_SIZE); + + return GRUB_ERR_NONE; @@ grub-core/disk/luks2.c (new) + gcry_err_code_t gcry_ret; + + /* Decode both digest and salt */ -+ if (!base64_decode(d->digest, grub_strlen (d->digest), (char *)digest, &digestlen)) ++ if (!base64_decode (d->digest, grub_strlen (d->digest), (char *)digest, &digestlen)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest"); -+ if (!base64_decode(d->salt, grub_strlen (d->salt), (char *)salt, &saltlen)) ++ if (!base64_decode (d->salt, grub_strlen (d->salt), (char *)salt, &saltlen)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest salt"); + + /* Configure the hash used for the digest. */ @@ grub-core/disk/luks2.c (new) + gcry_err_code_t gcry_ret; + grub_err_t ret; + -+ if (!base64_decode(k->kdf.salt, grub_strlen (k->kdf.salt), ++ if (!base64_decode (k->kdf.salt, grub_strlen (k->kdf.salt), + (char *)salt, &saltlen)) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot salt"); @@ grub-core/disk/luks2.c (new) + } + + /* Set up disk encryption parameters for the key area */ -+ grub_strncpy (cipher, k->area.encryption, sizeof(cipher)); ++ grub_strncpy (cipher, k->area.encryption, sizeof (cipher)); + p = grub_memchr (cipher, '-', grub_strlen (cipher)); + if (!p) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid encryption"); @@ grub-core/disk/luks2.c (new) + grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + char passphrase[MAX_PASSPHRASE], cipher[32]; + char *json_header = NULL, *part = NULL, *ptr; -+ grub_size_t candidate_key_len = 0, i; ++ grub_size_t candidate_key_len = 0, i, size; + grub_luks2_header_t header; + grub_luks2_keyslot_t keyslot; + grub_luks2_digest_t digest; @@ grub-core/disk/luks2.c (new) + if (ret) + goto err; + -+ ptr = grub_memchr(json_header, 0, grub_be_to_cpu64 (header.hdr_size) - sizeof (header)); ++ ptr = grub_memchr (json_header, 0, grub_be_to_cpu64 (header.hdr_size) - sizeof (header)); + if (!ptr) + goto err; + @@ grub-core/disk/luks2.c (new) + goto err; + } + -+ ret = grub_json_getvalue (&keyslots, json, "keyslots"); -+ if (ret) ++ if (grub_json_getvalue (&keyslots, json, "keyslots") || ++ grub_json_getsize (&size, &keyslots)) ++ { ++ ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get keyslots"); + goto err; ++ } + + /* Try all keyslot */ -+ for (i = 0; i < grub_json_getsize (&keyslots); i++) ++ for (i = 0; i < size; i++) + { + ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, i); + if (ret) @@ grub-core/disk/luks2.c (new) + if (grub_strcmp (segment.size, "dynamic") == 0) + crypt->total_length = grub_disk_get_size (disk) - crypt->offset; + else -+ crypt->total_length = grub_strtoull(segment.size, NULL, 10); ++ crypt->total_length = grub_strtoull (segment.size, NULL, 10); + + ret = luks2_decrypt_key (candidate_key, disk, crypt, &keyslot, + (const grub_uint8_t *) passphrase, grub_strlen (passphrase)); @@ grub-core/disk/luks2.c (new) + } + + /* Set up disk cipher. */ -+ grub_strncpy (cipher, segment.encryption, sizeof(cipher)); ++ grub_strncpy (cipher, segment.encryption, sizeof (cipher)); + ptr = grub_memchr (cipher, '-', grub_strlen (cipher)); + if (!ptr) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid encryption"); -- 2.24.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel