mirror of https://github.com/ipxe/ipxe.git
[crypto] New command imgdigest, verify image using digest
The imgdigest works like imgverify, expect that the image is verified using a digest instead of a signature.pull/34/head
parent
03e71d5d1a
commit
76c7cdb0b2
|
@ -161,6 +161,69 @@ static int imgverify_exec ( int argc, char **argv ) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
/** "imgdigest" options */
|
||||
struct imgdigest_options {
|
||||
/** Download timeout */
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
/** "imgdigest" option list */
|
||||
static struct option_descriptor imgdigest_opts[] = {
|
||||
OPTION_DESC ( "timeout", 't', required_argument,
|
||||
struct imgdigest_options, timeout, parse_timeout),
|
||||
};
|
||||
|
||||
/** "imgdigest" command descriptor */
|
||||
static struct command_descriptor imgdigest_cmd =
|
||||
COMMAND_DESC ( struct imgdigest_options, imgdigest_opts, 3, 3,
|
||||
"<uri|image> <digestname> <digest>" );
|
||||
|
||||
/**
|
||||
* The "imgdigest" command
|
||||
*
|
||||
* @v argc Argument count
|
||||
* @v argv Argument list
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int imgdigest_exec ( int argc, char **argv ) {
|
||||
struct imgdigest_options opts;
|
||||
struct image *image;
|
||||
const char *image_name_uri;
|
||||
const char *digest_name;
|
||||
const char *digest;
|
||||
int rc;
|
||||
|
||||
/* Parse options */
|
||||
if ( ( rc = parse_options ( argc, argv, &imgdigest_cmd, &opts ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Parse image name/URI string */
|
||||
image_name_uri = argv[optind];
|
||||
|
||||
/* Parse digest name */
|
||||
digest_name = argv[ optind + 1 ];
|
||||
|
||||
/* Parse digest string */
|
||||
digest = argv[ optind + 2 ];
|
||||
|
||||
/* Acquire the image */
|
||||
if ( ( rc = imgacquire ( image_name_uri, opts.timeout, &image ) ) != 0 )
|
||||
goto err_acquire_image;
|
||||
|
||||
/* Verify image */
|
||||
if ( ( rc = imgverifydigest ( image, digest_name, digest ) ) != 0 ) {
|
||||
printf ( "Could not verify: %s\n", strerror ( rc ) );
|
||||
goto err_verify;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
rc = 0;
|
||||
|
||||
err_verify:
|
||||
err_acquire_image:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** Image trust management commands */
|
||||
struct command image_trust_commands[] __command = {
|
||||
{
|
||||
|
@ -171,6 +234,10 @@ struct command image_trust_commands[] __command = {
|
|||
.name = "imgverify",
|
||||
.exec = imgverify_exec,
|
||||
},
|
||||
{
|
||||
.name = "imgdigest",
|
||||
.exec = imgdigest_exec,
|
||||
},
|
||||
};
|
||||
|
||||
/* Drag in objects via command list */
|
||||
|
|
|
@ -14,4 +14,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
extern int imgverify ( struct image *image, struct image *signature,
|
||||
const char *name );
|
||||
|
||||
extern int imgverifydigest ( struct image *image, const char *digest_name,
|
||||
const char *digest );
|
||||
|
||||
#endif /* _USR_IMGTRUST_H */
|
||||
|
|
|
@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <ipxe/uaccess.h>
|
||||
#include <ipxe/image.h>
|
||||
#include <ipxe/cms.h>
|
||||
#include <ipxe/base16.h>
|
||||
#include <ipxe/validator.h>
|
||||
#include <ipxe/monojob.h>
|
||||
#include <usr/imgtrust.h>
|
||||
|
@ -112,3 +113,109 @@ int imgverify ( struct image *image, struct image *signature,
|
|||
image->name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate digest of user data
|
||||
*
|
||||
* @v digest Digest alogorithm
|
||||
* @v data Data to digest
|
||||
* @v len Length of data
|
||||
* @v out Digest output
|
||||
*/
|
||||
static void digest_user_data ( struct digest_algorithm *digest, userptr_t data,
|
||||
size_t len, void *out ) {
|
||||
uint8_t ctx[ digest->ctxsize ];
|
||||
uint8_t block[ digest->blocksize ];
|
||||
size_t offset = 0;
|
||||
size_t frag_len;
|
||||
|
||||
/* Initialise digest */
|
||||
digest_init ( digest, ctx );
|
||||
|
||||
/* Process data one block at a time */
|
||||
while ( len ) {
|
||||
frag_len = len;
|
||||
if ( frag_len > sizeof ( block ) )
|
||||
frag_len = sizeof ( block );
|
||||
copy_from_user ( block, data, offset, frag_len );
|
||||
digest_update ( digest, ctx, block, frag_len );
|
||||
offset += frag_len;
|
||||
len -= frag_len;
|
||||
}
|
||||
|
||||
/* Finalise digest */
|
||||
digest_final ( digest, ctx, out );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Identify a digest algorithm by name
|
||||
*
|
||||
* @v name Digest name
|
||||
|
||||
* @ret digest Digest algorithm, or NULL
|
||||
*/
|
||||
static struct digest_algorithm *
|
||||
find_digest_algorithm ( const char *name ) {
|
||||
struct asn1_algorithm *algorithm;
|
||||
|
||||
for_each_table_entry ( algorithm, ASN1_ALGORITHMS ) {
|
||||
if ( strcmp ( algorithm->name, name ) == 0
|
||||
&& algorithm->digest )
|
||||
return algorithm->digest;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify image using the supplied digest
|
||||
*
|
||||
* @v image Image to verify
|
||||
* @v digest_name Name of digest algorithm to use
|
||||
* @v hex Hex encoded digest
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int imgverifydigest ( struct image *image, const char *digest_name,
|
||||
const char *hex ) {
|
||||
struct digest_algorithm *digest;
|
||||
uint8_t in[ base16_decoded_max_len ( hex ) ];
|
||||
uint8_t out[ base16_decoded_max_len ( hex ) ];
|
||||
int rc;
|
||||
|
||||
/* Mark image as untrusted */
|
||||
image_untrust ( image );
|
||||
|
||||
/* Parse digest name */
|
||||
if ( ! ( digest = find_digest_algorithm ( digest_name ) ) ) {
|
||||
syslog ( LOG_ERR, "Invalid digest name: %s\n", digest_name );
|
||||
rc = -EINVAL;
|
||||
goto err_verify;
|
||||
}
|
||||
|
||||
/* Parse hex input digest */
|
||||
if ( base16_decode ( hex, in ) != (int) digest->digestsize ) {
|
||||
syslog ( LOG_ERR, "Invalid digest: %s %s\n", digest_name, hex );
|
||||
rc = -EINVAL;
|
||||
goto err_verify;
|
||||
}
|
||||
|
||||
/* Verify digest */
|
||||
digest_user_data ( digest, image->data, image->len, out );
|
||||
if ( memcmp ( in, out, digest->digestsize ) != 0 ) {
|
||||
rc = -EINVAL;
|
||||
goto err_verify;
|
||||
}
|
||||
|
||||
/* Mark image as trusted */
|
||||
image_trust ( image );
|
||||
syslog ( LOG_NOTICE, "Image \"%s\" digest OK\n", image->name );
|
||||
|
||||
return 0;
|
||||
|
||||
err_verify:
|
||||
syslog ( LOG_ERR, "Image \"%s\" digest bad: %s\n",
|
||||
image->name, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue