提交 d79ae6aa 编写于 作者: T Tom Rini

Merge branch '2019-12-06-master-imports'

- Allow for the sysboot command, which is used to parse extlinux.conf
  files to be used without PXE support.  There is no functional change
  here aside from fixing distro boot in a few cases where we actually
  lacked the ability to parse the extlinux.conf file
- Add the x509/pkcs7 parsers from Linux, a pre-requisite to EFI Secure
  Boot support.
......@@ -88,6 +88,7 @@ config DISTRO_DEFAULTS
select CMD_PART if PARTITIONS
select CMD_PING if CMD_NET
select CMD_PXE if NET
select CMD_SYSBOOT
select ENV_VARS_UBOOT_CONFIG
select HUSH_PARSER
select SUPPORT_RAW_INITRD
......
......@@ -1889,6 +1889,7 @@ checkarmreloc: u-boot
fi
tools/version.h: include/version.h
$(Q)mkdir -p $(dir $@)
$(call if_changed,copy)
envtools: scripts_basic $(version_h) $(timestamp_h) tools/version.h
......@@ -1957,6 +1958,7 @@ clean: $(clean-dirs)
-o -name '*.ko.*' -o -name '*.su' -o -name '*.pyc' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
-o -name '*.asn1.[ch]' \
-o -name '*.symtypes' -o -name 'modules.order' \
-o -name modules.builtin -o -name '.tmp_*.o.*' \
-o -name 'dsdt.aml' -o -name 'dsdt.asl.tmp' -o -name 'dsdt.c' \
......
......@@ -1625,6 +1625,7 @@ config CMD_LED
config CMD_DATE
bool "date"
default y if DM_RTC
select LIB_DATE
help
Enable the 'date' command for getting/setting the time/date in RTC
devices.
......@@ -1671,6 +1672,12 @@ config CMD_SOUND
sound init - set up sound system
sound play - play a sound
config CMD_SYSBOOT
bool "sysboot"
select MENU
help
Boot image via local extlinux.conf file
config CMD_QFW
bool "qfw"
select QFW
......
......@@ -111,7 +111,7 @@ ifdef CONFIG_PCI
obj-$(CONFIG_CMD_PCI) += pci.o
endif
obj-$(CONFIG_CMD_PINMUX) += pinmux.o
obj-$(CONFIG_CMD_PXE) += pxe.o
obj-$(CONFIG_CMD_PXE) += pxe.o pxe_utils.o
obj-$(CONFIG_CMD_WOL) += wol.o
obj-$(CONFIG_CMD_QFW) += qfw.o
obj-$(CONFIG_CMD_READ) += read.o
......@@ -130,6 +130,7 @@ obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
obj-$(CONFIG_CMD_SPI) += spi.o
obj-$(CONFIG_CMD_STRINGS) += strings.o
obj-$(CONFIG_CMD_SMC) += smccc.o
obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o pxe_utils.o
obj-$(CONFIG_CMD_TERMINAL) += terminal.o
obj-$(CONFIG_CMD_TIME) += time.o
obj-$(CONFIG_CMD_TRACE) += trace.o
......
......@@ -681,6 +681,23 @@ char *env_get(const char *name)
return NULL;
}
/*
* Like env_get, but prints an error if envvar isn't defined in the
* environment. It always returns what env_get does, so it can be used in
* place of env_get without changing error handling otherwise.
*/
char *from_env(const char *envvar)
{
char *ret;
ret = env_get(envvar);
if (!ret)
printf("missing environment variable: %s\n", envvar);
return ret;
}
/*
* Look up variable from environment for restricted C runtime env.
*/
......
此差异已折叠。
此差异已折叠。
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __PXE_UTILS_H
#define __PXE_UTILS_H
/*
* A note on the pxe file parser.
*
* We're parsing files that use syslinux grammar, which has a few quirks.
* String literals must be recognized based on context - there is no
* quoting or escaping support. There's also nothing to explicitly indicate
* when a label section completes. We deal with that by ending a label
* section whenever we see a line that doesn't include.
*
* As with the syslinux family, this same file format could be reused in the
* future for non pxe purposes. The only action it takes during parsing that
* would throw this off is handling of include files. It assumes we're using
* pxe, and does a tftp download of a file listed as an include file in the
* middle of the parsing operation. That could be handled by refactoring it to
* take a 'include file getter' function.
*/
/*
* Describes a single label given in a pxe file.
*
* Create these with the 'label_create' function given below.
*
* name - the name of the menu as given on the 'menu label' line.
* kernel - the path to the kernel file to use for this label.
* append - kernel command line to use when booting this label
* initrd - path to the initrd to use for this label.
* attempted - 0 if we haven't tried to boot this label, 1 if we have.
* localboot - 1 if this label specified 'localboot', 0 otherwise.
* list - lets these form a list, which a pxe_menu struct will hold.
*/
struct pxe_label {
char num[4];
char *name;
char *menu;
char *kernel;
char *config;
char *append;
char *initrd;
char *fdt;
char *fdtdir;
int ipappend;
int attempted;
int localboot;
int localboot_val;
struct list_head list;
};
/*
* Describes a pxe menu as given via pxe files.
*
* title - the name of the menu as given by a 'menu title' line.
* default_label - the name of the default label, if any.
* bmp - the bmp file name which is displayed in background
* timeout - time in tenths of a second to wait for a user key-press before
* booting the default label.
* prompt - if 0, don't prompt for a choice unless the timeout period is
* interrupted. If 1, always prompt for a choice regardless of
* timeout.
* labels - a list of labels defined for the menu.
*/
struct pxe_menu {
char *title;
char *default_label;
char *bmp;
int timeout;
int prompt;
struct list_head labels;
};
extern bool is_pxe;
extern int (*do_getfile)(cmd_tbl_t *cmdtp, const char *file_path,
char *file_addr);
void destroy_pxe_menu(struct pxe_menu *cfg);
int get_pxe_file(cmd_tbl_t *cmdtp, const char *file_path,
unsigned long file_addr);
int get_pxelinux_path(cmd_tbl_t *cmdtp, const char *file,
unsigned long pxefile_addr_r);
void handle_pxe_menu(cmd_tbl_t *cmdtp, struct pxe_menu *cfg);
struct pxe_menu *parse_pxefile(cmd_tbl_t *cmdtp, unsigned long menucfg);
int format_mac_pxe(char *outbuf, size_t outbuf_len);
#endif /* __PXE_UTILS_H */
// SPDX-License-Identifier: GPL-2.0+
#include <common.h>
#include <command.h>
#include <env.h>
#include <fs.h>
#include "pxe_utils.h"
static char *fs_argv[5];
static int do_get_ext2(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
{
#ifdef CONFIG_CMD_EXT2
fs_argv[0] = "ext2load";
fs_argv[3] = file_addr;
fs_argv[4] = (void *)file_path;
if (!do_ext2load(cmdtp, 0, 5, fs_argv))
return 1;
#endif
return -ENOENT;
}
static int do_get_fat(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
{
#ifdef CONFIG_CMD_FAT
fs_argv[0] = "fatload";
fs_argv[3] = file_addr;
fs_argv[4] = (void *)file_path;
if (!do_fat_fsload(cmdtp, 0, 5, fs_argv))
return 1;
#endif
return -ENOENT;
}
static int do_get_any(cmd_tbl_t *cmdtp, const char *file_path, char *file_addr)
{
#ifdef CONFIG_CMD_FS_GENERIC
fs_argv[0] = "load";
fs_argv[3] = file_addr;
fs_argv[4] = (void *)file_path;
if (!do_load(cmdtp, 0, 5, fs_argv, FS_TYPE_ANY))
return 1;
#endif
return -ENOENT;
}
/*
* Boots a system using a local disk syslinux/extlinux file
*
* Returns 0 on success, 1 on error.
*/
static int do_sysboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
unsigned long pxefile_addr_r;
struct pxe_menu *cfg;
char *pxefile_addr_str;
char *filename;
int prompt = 0;
is_pxe = false;
if (argc > 1 && strstr(argv[1], "-p")) {
prompt = 1;
argc--;
argv++;
}
if (argc < 4)
return cmd_usage(cmdtp);
if (argc < 5) {
pxefile_addr_str = from_env("pxefile_addr_r");
if (!pxefile_addr_str)
return 1;
} else {
pxefile_addr_str = argv[4];
}
if (argc < 6) {
filename = env_get("bootfile");
} else {
filename = argv[5];
env_set("bootfile", filename);
}
if (strstr(argv[3], "ext2")) {
do_getfile = do_get_ext2;
} else if (strstr(argv[3], "fat")) {
do_getfile = do_get_fat;
} else if (strstr(argv[3], "any")) {
do_getfile = do_get_any;
} else {
printf("Invalid filesystem: %s\n", argv[3]);
return 1;
}
fs_argv[1] = argv[1];
fs_argv[2] = argv[2];
if (strict_strtoul(pxefile_addr_str, 16, &pxefile_addr_r) < 0) {
printf("Invalid pxefile address: %s\n", pxefile_addr_str);
return 1;
}
if (get_pxe_file(cmdtp, filename, pxefile_addr_r) < 0) {
printf("Error reading config file\n");
return 1;
}
cfg = parse_pxefile(cmdtp, pxefile_addr_r);
if (!cfg) {
printf("Error parsing config file\n");
return 1;
}
if (prompt)
cfg->prompt = 1;
handle_pxe_menu(cmdtp, cfg);
destroy_pxe_menu(cfg);
return 0;
}
U_BOOT_CMD(sysboot, 7, 1, do_sysboot,
"command to get and boot from syslinux files",
"[-p] <interface> <dev[:part]> <ext2|fat|any> [addr] [filename]\n"
" - load and parse syslinux menu file 'filename' from ext2, fat\n"
" or any filesystem on 'dev' on 'interface' to address 'addr'"
);
ASN1
====
Abstract Syntax Notation One (or ASN1) is a standard by ITU-T and ISO/IEC
and used as a description language for defining data structure in
an independent manner.
Any data described in ASN1 notation can be serialized (or encoded) and
de-serialized (or decoded) with well-defined encoding rules.
A combination of ASN1 compiler and ASN1 decoder library function will
provide a function interface for parsing encoded binary into specific
data structure:
1) define data structure in a text file (*.asn1)
2) define "action" routines for specific "tags" defined in (1)
3) generate bytecode as a C file (*.asn1.[ch]) from *.asn1 file
with ASN1 compiler (tools/asn1_compiler)
4) call a ASN1 decoder (asn1_ber_decoder()) with bytecode and data
Usage of ASN1 compiler
----------------------
asn1_compiler [-v] [-d] <grammar-file> <c-file> <hdr-file>
<grammar-file>: ASN1 input file
<c-file>: generated C file
<hdr-file>: generated include file
Usage of ASN1 decoder
---------------------
int asn1_ber_decoder(const struct asn1_decoder *decoder, void *context,
const unsigned char *data, size_t datalen);
@decoder: bytecode binary
@context: context for decoder
@data: data to be parsed
@datalen: size of data
As of writing this, ASN1 compiler and decoder are used to implement
X509 certificate parser, pcks7 message parser and RSA public key parser
for UEFI secure boot.
......@@ -7,6 +7,7 @@ menu "Real Time Clock"
config DM_RTC
bool "Enable Driver Model for RTC drivers"
depends on DM
select LIB_DATE
help
Enable drver model for real-time-clock drivers. The RTC uclass
then provides the rtc_get()/rtc_set() interface, delegating to
......
......@@ -7,7 +7,6 @@
obj-$(CONFIG_$(SPL_TPL_)DM_RTC) += rtc-uclass.o
obj-$(CONFIG_RTC_AT91SAM9_RTT) += at91sam9_rtt.o
obj-y += date.o
obj-y += rtc-lib.o
obj-$(CONFIG_RTC_DAVINCI) += davinci.o
obj-$(CONFIG_RTC_DS1302) += ds1302.o
......
......@@ -18,6 +18,7 @@
#include "ubifs.h"
#include <u-boot/zlib.h>
#include <linux/compat.h>
#include <linux/err.h>
#include <linux/lzo.h>
......@@ -70,24 +71,6 @@ struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
#ifdef __UBOOT__
/* from mm/util.c */
/**
* kmemdup - duplicate region of memory
*
* @src: memory region to duplicate
* @len: memory region length
* @gfp: GFP mask to use
*/
void *kmemdup(const void *src, size_t len, gfp_t gfp)
{
void *p;
p = kmalloc(len, gfp);
if (p)
memcpy(p, src, len);
return p;
}
struct crypto_comp {
int compressor;
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* RSA internal helpers
*
* Copyright (c) 2015, Intel Corporation
* Authors: Tadeusz Struk <tadeusz.struk@intel.com>
*/
#ifndef _RSA_HELPER_
#define _RSA_HELPER_
#include <linux/types.h>
/**
* rsa_key - RSA key structure
* @n : RSA modulus raw byte stream
* @e : RSA public exponent raw byte stream
* @d : RSA private exponent raw byte stream
* @p : RSA prime factor p of n raw byte stream
* @q : RSA prime factor q of n raw byte stream
* @dp : RSA exponent d mod (p - 1) raw byte stream
* @dq : RSA exponent d mod (q - 1) raw byte stream
* @qinv : RSA CRT coefficient q^(-1) mod p raw byte stream
* @n_sz : length in bytes of RSA modulus n
* @e_sz : length in bytes of RSA public exponent
* @d_sz : length in bytes of RSA private exponent
* @p_sz : length in bytes of p field
* @q_sz : length in bytes of q field
* @dp_sz : length in bytes of dp field
* @dq_sz : length in bytes of dq field
* @qinv_sz : length in bytes of qinv field
*/
struct rsa_key {
const u8 *n;
const u8 *e;
const u8 *d;
const u8 *p;
const u8 *q;
const u8 *dp;
const u8 *dq;
const u8 *qinv;
size_t n_sz;
size_t e_sz;
size_t d_sz;
size_t p_sz;
size_t q_sz;
size_t dp_sz;
size_t dq_sz;
size_t qinv_sz;
};
int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
unsigned int key_len);
int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
unsigned int key_len);
extern struct crypto_template rsa_pkcs1pad_tmpl;
#endif
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* PKCS#7 crypto data parser
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _CRYPTO_PKCS7_H
#define _CRYPTO_PKCS7_H
#ifndef __UBOOT__
#include <linux/verification.h>
#include <crypto/public_key.h>
#endif
struct key;
struct pkcs7_message;
/*
* pkcs7_parser.c
*/
extern struct pkcs7_message *pkcs7_parse_message(const void *data,
size_t datalen);
extern void pkcs7_free_message(struct pkcs7_message *pkcs7);
extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
const void **_data, size_t *_datalen,
size_t *_headerlen);
#ifndef __UBOOT__
/*
* pkcs7_trust.c
*/
extern int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
struct key *trust_keyring);
/*
* pkcs7_verify.c
*/
extern int pkcs7_verify(struct pkcs7_message *pkcs7,
enum key_being_used_for usage);
extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
const void *data, size_t datalen);
#endif
#endif /* _CRYPTO_PKCS7_H */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Asymmetric public-key algorithm definitions
*
* See Documentation/crypto/asymmetric-keys.txt
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _LINUX_PUBLIC_KEY_H
#define _LINUX_PUBLIC_KEY_H
#ifdef __UBOOT__
#include <linux/types.h>
#else
#include <linux/keyctl.h>
#endif
#include <linux/oid_registry.h>
/*
* Cryptographic data for the public-key subtype of the asymmetric key type.
*
* Note that this may include private part of the key as well as the public
* part.
*/
struct public_key {
void *key;
u32 keylen;
enum OID algo;
void *params;
u32 paramlen;
bool key_is_private;
const char *id_type;
const char *pkey_algo;
};
extern void public_key_free(struct public_key *key);
/*
* Public key cryptography signature data
*/
struct public_key_signature {
struct asymmetric_key_id *auth_ids[2];
u8 *s; /* Signature */
u32 s_size; /* Number of bytes in signature */
u8 *digest;
u8 digest_size; /* Number of bytes in digest */
const char *pkey_algo;
const char *hash_algo;
const char *encoding;
};
extern void public_key_signature_free(struct public_key_signature *sig);
#ifndef __UBOOT__
extern struct asymmetric_key_subtype public_key_subtype;
struct key;
struct key_type;
union key_payload;
extern int restrict_link_by_signature(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trust_keyring);
extern int restrict_link_by_key_or_keyring(struct key *dest_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trusted);
extern int restrict_link_by_key_or_keyring_chain(struct key *trust_keyring,
const struct key_type *type,
const union key_payload *payload,
struct key *trusted);
extern int query_asymmetric_key(const struct kernel_pkey_params *,
struct kernel_pkey_query *);
extern int encrypt_blob(struct kernel_pkey_params *, const void *, void *);
extern int decrypt_blob(struct kernel_pkey_params *, const void *, void *);
extern int create_signature(struct kernel_pkey_params *, const void *, void *);
extern int verify_signature(const struct key *,
const struct public_key_signature *);
int public_key_verify_signature(const struct public_key *pkey,
const struct public_key_signature *sig);
#endif /* !__UBOOT__ */
#endif /* _LINUX_PUBLIC_KEY_H */
......@@ -113,6 +113,16 @@ int env_match(unsigned char *name, int index);
*/
char *env_get(const char *varname);
/*
* Like env_get, but prints an error if envvar isn't defined in the
* environment. It always returns what env_get does, so it can be used in
* place of env_get without changing error handling otherwise.
*
* @varname: Variable to look up
* @return value of variable, or NULL if not found
*/
char *from_env(const char *envvar);
/**
* env_get_f() - Look up the value of an environment variable (early)
*
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Asymmetric Public-key cryptography key type interface
*
* See Documentation/crypto/asymmetric-keys.txt
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _KEYS_ASYMMETRIC_TYPE_H
#define _KEYS_ASYMMETRIC_TYPE_H
#ifndef __UBOOT__
#include <linux/key-type.h>
#include <linux/verification.h>
extern struct key_type key_type_asymmetric;
/*
* The key payload is four words. The asymmetric-type key uses them as
* follows:
*/
enum asymmetric_payload_bits {
asym_crypto, /* The data representing the key */
asym_subtype, /* Pointer to an asymmetric_key_subtype struct */
asym_key_ids, /* Pointer to an asymmetric_key_ids struct */
asym_auth /* The key's authorisation (signature, parent key ID) */
};
#endif /* !__UBOOT__ */
/*
* Identifiers for an asymmetric key ID. We have three ways of looking up a
* key derived from an X.509 certificate:
*
* (1) Serial Number & Issuer. Non-optional. This is the only valid way to
* map a PKCS#7 signature to an X.509 certificate.
*
* (2) Issuer & Subject Unique IDs. Optional. These were the original way to
* match X.509 certificates, but have fallen into disuse in favour of (3).
*
* (3) Auth & Subject Key Identifiers. Optional. SKIDs are only provided on
* CA keys that are intended to sign other keys, so don't appear in end
* user certificates unless forced.
*
* We could also support an PGP key identifier, which is just a SHA1 sum of the
* public key and certain parameters, but since we don't support PGP keys at
* the moment, we shall ignore those.
*
* What we actually do is provide a place where binary identifiers can be
* stashed and then compare against them when checking for an id match.
*/
struct asymmetric_key_id {
unsigned short len;
unsigned char data[];
};
struct asymmetric_key_ids {
void *id[2];
};
extern bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
const struct asymmetric_key_id *kid2);
extern bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
const struct asymmetric_key_id *kid2);
extern struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
size_t len_1,
const void *val_2,
size_t len_2);
#ifndef __UBOOT__
static inline
const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
{
return key->payload.data[asym_key_ids];
}
extern struct key *find_asymmetric_key(struct key *keyring,
const struct asymmetric_key_id *id_0,
const struct asymmetric_key_id *id_1,
bool partial);
#endif
/*
* The payload is at the discretion of the subtype.
*/
#endif /* _KEYS_ASYMMETRIC_TYPE_H */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* ASN.1 BER/DER/CER encoding definitions
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _LINUX_ASN1_H
#define _LINUX_ASN1_H
/* Class */
enum asn1_class {
ASN1_UNIV = 0, /* Universal */
ASN1_APPL = 1, /* Application */
ASN1_CONT = 2, /* Context */
ASN1_PRIV = 3 /* Private */
};
#define ASN1_CLASS_BITS 0xc0
enum asn1_method {
ASN1_PRIM = 0, /* Primitive */
ASN1_CONS = 1 /* Constructed */
};
#define ASN1_CONS_BIT 0x20
/* Tag */
enum asn1_tag {
ASN1_EOC = 0, /* End Of Contents or N/A */
ASN1_BOOL = 1, /* Boolean */
ASN1_INT = 2, /* Integer */
ASN1_BTS = 3, /* Bit String */
ASN1_OTS = 4, /* Octet String */
ASN1_NULL = 5, /* Null */
ASN1_OID = 6, /* Object Identifier */
ASN1_ODE = 7, /* Object Description */
ASN1_EXT = 8, /* External */
ASN1_REAL = 9, /* Real float */
ASN1_ENUM = 10, /* Enumerated */
ASN1_EPDV = 11, /* Embedded PDV */
ASN1_UTF8STR = 12, /* UTF8 String */
ASN1_RELOID = 13, /* Relative OID */
/* 14 - Reserved */
/* 15 - Reserved */
ASN1_SEQ = 16, /* Sequence and Sequence of */
ASN1_SET = 17, /* Set and Set of */
ASN1_NUMSTR = 18, /* Numerical String */
ASN1_PRNSTR = 19, /* Printable String */
ASN1_TEXSTR = 20, /* T61 String / Teletext String */
ASN1_VIDSTR = 21, /* Videotex String */
ASN1_IA5STR = 22, /* IA5 String */
ASN1_UNITIM = 23, /* Universal Time */
ASN1_GENTIM = 24, /* General Time */
ASN1_GRASTR = 25, /* Graphic String */
ASN1_VISSTR = 26, /* Visible String */
ASN1_GENSTR = 27, /* General String */
ASN1_UNISTR = 28, /* Universal String */
ASN1_CHRSTR = 29, /* Character String */
ASN1_BMPSTR = 30, /* BMP String */
ASN1_LONG_TAG = 31 /* Long form tag */
};
#define ASN1_INDEFINITE_LENGTH 0x80
#endif /* _LINUX_ASN1_H */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* ASN.1 BER/DER/CER parsing state machine internal definitions
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _LINUX_ASN1_BER_BYTECODE_H
#define _LINUX_ASN1_BER_BYTECODE_H
#ifdef __KERNEL__
#include <linux/types.h>
#endif
#include <linux/asn1.h>
typedef int (*asn1_action_t)(void *context,
size_t hdrlen, /* In case of ANY type */
unsigned char tag, /* In case of ANY type */
const void *value, size_t vlen);
struct asn1_decoder {
const unsigned char *machine;
size_t machlen;
const asn1_action_t *actions;
};
enum asn1_opcode {
/* The tag-matching ops come first and the odd-numbered slots
* are for OR_SKIP ops.
*/
#define ASN1_OP_MATCH__SKIP 0x01
#define ASN1_OP_MATCH__ACT 0x02
#define ASN1_OP_MATCH__JUMP 0x04
#define ASN1_OP_MATCH__ANY 0x08
#define ASN1_OP_MATCH__COND 0x10
ASN1_OP_MATCH = 0x00,
ASN1_OP_MATCH_OR_SKIP = 0x01,
ASN1_OP_MATCH_ACT = 0x02,
ASN1_OP_MATCH_ACT_OR_SKIP = 0x03,
ASN1_OP_MATCH_JUMP = 0x04,
ASN1_OP_MATCH_JUMP_OR_SKIP = 0x05,
ASN1_OP_MATCH_ANY = 0x08,
ASN1_OP_MATCH_ANY_OR_SKIP = 0x09,
ASN1_OP_MATCH_ANY_ACT = 0x0a,
ASN1_OP_MATCH_ANY_ACT_OR_SKIP = 0x0b,
/* Everything before here matches unconditionally */
ASN1_OP_COND_MATCH_OR_SKIP = 0x11,
ASN1_OP_COND_MATCH_ACT_OR_SKIP = 0x13,
ASN1_OP_COND_MATCH_JUMP_OR_SKIP = 0x15,
ASN1_OP_COND_MATCH_ANY = 0x18,
ASN1_OP_COND_MATCH_ANY_OR_SKIP = 0x19,
ASN1_OP_COND_MATCH_ANY_ACT = 0x1a,
ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b,
/* Everything before here will want a tag from the data */
#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP
/* These are here to help fill up space */
ASN1_OP_COND_FAIL = 0x1c,
ASN1_OP_COMPLETE = 0x1d,
ASN1_OP_ACT = 0x1e,
ASN1_OP_MAYBE_ACT = 0x1f,
/* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */
ASN1_OP_END_SEQ = 0x20,
ASN1_OP_END_SET = 0x21,
ASN1_OP_END_SEQ_OF = 0x22,
ASN1_OP_END_SET_OF = 0x23,
ASN1_OP_END_SEQ_ACT = 0x24,
ASN1_OP_END_SET_ACT = 0x25,
ASN1_OP_END_SEQ_OF_ACT = 0x26,
ASN1_OP_END_SET_OF_ACT = 0x27,
#define ASN1_OP_END__SET 0x01
#define ASN1_OP_END__OF 0x02
#define ASN1_OP_END__ACT 0x04
ASN1_OP_RETURN = 0x28,
ASN1_OP__NR
};
#define _tag(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | ASN1_##TAG)
#define _tagn(CLASS, CP, TAG) ((ASN1_##CLASS << 6) | (ASN1_##CP << 5) | TAG)
#define _jump_target(N) (N)
#define _action(N) (N)
#endif /* _LINUX_ASN1_BER_BYTECODE_H */
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* ASN.1 decoder
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _LINUX_ASN1_DECODER_H
#define _LINUX_ASN1_DECODER_H
#include <linux/asn1.h>
struct asn1_decoder;
extern int asn1_ber_decoder(const struct asn1_decoder *decoder,
void *context,
const unsigned char *data,
size_t datalen);
#endif /* _LINUX_ASN1_DECODER_H */
#ifndef _LINUX_KERNEL_H
#define _LINUX_KERNEL_H
#include <linux/types.h>
#include <linux/printk.h> /* for printf/pr_* utilities */
#define USHRT_MAX ((u16)(~0U))
#define SHRT_MAX ((s16)(USHRT_MAX>>1))
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* ASN.1 Object identifier (OID) registry
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifndef _LINUX_OID_REGISTRY_H
#define _LINUX_OID_REGISTRY_H
#include <linux/types.h>
/*
* OIDs are turned into these values if possible, or OID__NR if not held here.
*
* NOTE! Do not mess with the format of each line as this is read by
* build_OID_registry.pl to generate the data for look_up_OID().
*/
enum OID {
OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */
OID_id_dsa, /* 1.2.840.10040.4.1 */
OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */
OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */
/* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */
OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */
OID_md2WithRSAEncryption, /* 1.2.840.113549.1.1.2 */
OID_md3WithRSAEncryption, /* 1.2.840.113549.1.1.3 */
OID_md4WithRSAEncryption, /* 1.2.840.113549.1.1.4 */
OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */
OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */
OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */
OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */
OID_sha224WithRSAEncryption, /* 1.2.840.113549.1.1.14 */
/* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */
OID_data, /* 1.2.840.113549.1.7.1 */
OID_signed_data, /* 1.2.840.113549.1.7.2 */
/* PKCS#9 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)} */
OID_email_address, /* 1.2.840.113549.1.9.1 */
OID_contentType, /* 1.2.840.113549.1.9.3 */
OID_messageDigest, /* 1.2.840.113549.1.9.4 */
OID_signingTime, /* 1.2.840.113549.1.9.5 */
OID_smimeCapabilites, /* 1.2.840.113549.1.9.15 */
OID_smimeAuthenticatedAttrs, /* 1.2.840.113549.1.9.16.2.11 */
/* {iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2)} */
OID_md2, /* 1.2.840.113549.2.2 */
OID_md4, /* 1.2.840.113549.2.4 */
OID_md5, /* 1.2.840.113549.2.5 */
/* Microsoft Authenticode & Software Publishing */
OID_msIndirectData, /* 1.3.6.1.4.1.311.2.1.4 */
OID_msStatementType, /* 1.3.6.1.4.1.311.2.1.11 */
OID_msSpOpusInfo, /* 1.3.6.1.4.1.311.2.1.12 */
OID_msPeImageDataObjId, /* 1.3.6.1.4.1.311.2.1.15 */
OID_msIndividualSPKeyPurpose, /* 1.3.6.1.4.1.311.2.1.21 */
OID_msOutlookExpress, /* 1.3.6.1.4.1.311.16.4 */
OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */
OID_sha1, /* 1.3.14.3.2.26 */
OID_sha256, /* 2.16.840.1.101.3.4.2.1 */
OID_sha384, /* 2.16.840.1.101.3.4.2.2 */
OID_sha512, /* 2.16.840.1.101.3.4.2.3 */
OID_sha224, /* 2.16.840.1.101.3.4.2.4 */
/* Distinguished Name attribute IDs [RFC 2256] */
OID_commonName, /* 2.5.4.3 */
OID_surname, /* 2.5.4.4 */
OID_countryName, /* 2.5.4.6 */
OID_locality, /* 2.5.4.7 */
OID_stateOrProvinceName, /* 2.5.4.8 */
OID_organizationName, /* 2.5.4.10 */
OID_organizationUnitName, /* 2.5.4.11 */
OID_title, /* 2.5.4.12 */
OID_description, /* 2.5.4.13 */
OID_name, /* 2.5.4.41 */
OID_givenName, /* 2.5.4.42 */
OID_initials, /* 2.5.4.43 */
OID_generationalQualifier, /* 2.5.4.44 */
/* Certificate extension IDs */
OID_subjectKeyIdentifier, /* 2.5.29.14 */
OID_keyUsage, /* 2.5.29.15 */
OID_subjectAltName, /* 2.5.29.17 */
OID_issuerAltName, /* 2.5.29.18 */
OID_basicConstraints, /* 2.5.29.19 */
OID_crlDistributionPoints, /* 2.5.29.31 */
OID_certPolicies, /* 2.5.29.32 */
OID_authorityKeyIdentifier, /* 2.5.29.35 */
OID_extKeyUsage, /* 2.5.29.37 */
/* EC-RDSA */
OID_gostCPSignA, /* 1.2.643.2.2.35.1 */
OID_gostCPSignB, /* 1.2.643.2.2.35.2 */
OID_gostCPSignC, /* 1.2.643.2.2.35.3 */
OID_gost2012PKey256, /* 1.2.643.7.1.1.1.1 */
OID_gost2012PKey512, /* 1.2.643.7.1.1.1.2 */
OID_gost2012Digest256, /* 1.2.643.7.1.1.2.2 */
OID_gost2012Digest512, /* 1.2.643.7.1.1.2.3 */
OID_gost2012Signature256, /* 1.2.643.7.1.1.3.2 */
OID_gost2012Signature512, /* 1.2.643.7.1.1.3.3 */
OID_gostTC26Sign256A, /* 1.2.643.7.1.2.1.1.1 */
OID_gostTC26Sign256B, /* 1.2.643.7.1.2.1.1.2 */
OID_gostTC26Sign256C, /* 1.2.643.7.1.2.1.1.3 */
OID_gostTC26Sign256D, /* 1.2.643.7.1.2.1.1.4 */
OID_gostTC26Sign512A, /* 1.2.643.7.1.2.1.2.1 */
OID_gostTC26Sign512B, /* 1.2.643.7.1.2.1.2.2 */
OID_gostTC26Sign512C, /* 1.2.643.7.1.2.1.2.3 */
OID__NR
};
extern enum OID look_up_OID(const void *data, size_t datasize);
extern int sprint_oid(const void *, size_t, char *, size_t);
extern int sprint_OID(enum OID, char *, size_t);
#endif /* _LINUX_OID_REGISTRY_H */
#ifndef _LINUX_TIME_H
#define _LINUX_TIME_H
#include <rtc.h>
#include <vsprintf.h>
#include <linux/types.h>
#define _DEFUN(a,b,c) a(c)
......@@ -150,4 +152,13 @@ _DEFUN (ctime_r, (tim_p, result),
return asctime_r (localtime_r (tim_p, &tm), result);
}
/* for compatibility with linux code */
typedef __s64 time64_t;
#ifdef CONFIG_LIB_DATE
time64_t mktime64(const unsigned int year, const unsigned int mon,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec);
#endif
#endif
......@@ -18,6 +18,8 @@
#ifdef CONFIG_DM_RTC
struct udevice;
struct rtc_ops {
/**
* get() - get the current time
......
......@@ -265,6 +265,7 @@ config AES
present.
source lib/rsa/Kconfig
source lib/crypto/Kconfig
config TPM
bool "Trusted Platform Module (TPM) Support"
......@@ -566,6 +567,19 @@ config SMBIOS_PRODUCT_NAME
endmenu
config ASN1_COMPILER
bool
config ASN1_DECODER
bool
help
Enable asn1 decoder library.
config OID_REGISTRY
bool
help
Enable fast lookup object identifier registry.
source lib/efi/Kconfig
source lib/efi_loader/Kconfig
source lib/optee/Kconfig
......@@ -574,4 +588,7 @@ config TEST_FDTDEC
bool "enable fdtdec test"
depends on OF_LIBFDT
config LIB_DATE
bool
endmenu
......@@ -17,6 +17,8 @@ obj-$(CONFIG_OF_LIVE) += of_live.o
obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
obj-$(CONFIG_ARCH_AT91) += at91/
obj-$(CONFIG_OPTEE) += optee/
obj-$(CONFIG_ASN1_DECODER) += asn1_decoder.o
obj-y += crypto/
obj-$(CONFIG_AES) += aes.o
......@@ -117,4 +119,22 @@ else
obj-y += vsprintf.o strto.o
endif
obj-y += date.o
#
# Build a fast OID lookup registry from include/linux/oid_registry.h
#
obj-$(CONFIG_OID_REGISTRY) += oid_registry.o
$(obj)/oid_registry.o: $(obj)/oid_registry_data.c
$(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \
$(srctree)/scripts/build_OID_registry
$(call cmd,build_OID_registry)
quiet_cmd_build_OID_registry = GEN $@
cmd_build_OID_registry = perl $(srctree)/scripts/build_OID_registry $< $@
clean-files += oid_registry_data.c
subdir-ccflags-$(CONFIG_CC_OPTIMIZE_LIBS_FOR_SPEED) += -O2
// SPDX-License-Identifier: GPL-2.0-or-later
/* Decoder for ASN.1 BER/DER/CER encoded bytestream
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#ifdef __UBOOT__
#include <linux/compat.h>
#else
#include <linux/export.h>
#endif
#include <linux/kernel.h>
#include <linux/errno.h>
#ifndef __UBOOT__
#include <linux/module.h>
#endif
#include <linux/asn1_decoder.h>
#include <linux/asn1_ber_bytecode.h>
static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
/* OPC TAG JMP ACT */
[ASN1_OP_MATCH] = 1 + 1,
[ASN1_OP_MATCH_OR_SKIP] = 1 + 1,
[ASN1_OP_MATCH_ACT] = 1 + 1 + 1,
[ASN1_OP_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
[ASN1_OP_MATCH_JUMP] = 1 + 1 + 1,
[ASN1_OP_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
[ASN1_OP_MATCH_ANY] = 1,
[ASN1_OP_MATCH_ANY_OR_SKIP] = 1,
[ASN1_OP_MATCH_ANY_ACT] = 1 + 1,
[ASN1_OP_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
[ASN1_OP_COND_MATCH_OR_SKIP] = 1 + 1,
[ASN1_OP_COND_MATCH_ACT_OR_SKIP] = 1 + 1 + 1,
[ASN1_OP_COND_MATCH_JUMP_OR_SKIP] = 1 + 1 + 1,
[ASN1_OP_COND_MATCH_ANY] = 1,
[ASN1_OP_COND_MATCH_ANY_OR_SKIP] = 1,
[ASN1_OP_COND_MATCH_ANY_ACT] = 1 + 1,
[ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP] = 1 + 1,
[ASN1_OP_COND_FAIL] = 1,
[ASN1_OP_COMPLETE] = 1,
[ASN1_OP_ACT] = 1 + 1,
[ASN1_OP_MAYBE_ACT] = 1 + 1,
[ASN1_OP_RETURN] = 1,
[ASN1_OP_END_SEQ] = 1,
[ASN1_OP_END_SEQ_OF] = 1 + 1,
[ASN1_OP_END_SET] = 1,
[ASN1_OP_END_SET_OF] = 1 + 1,
[ASN1_OP_END_SEQ_ACT] = 1 + 1,
[ASN1_OP_END_SEQ_OF_ACT] = 1 + 1 + 1,
[ASN1_OP_END_SET_ACT] = 1 + 1,
[ASN1_OP_END_SET_OF_ACT] = 1 + 1 + 1,
};
/*
* Find the length of an indefinite length object
* @data: The data buffer
* @datalen: The end of the innermost containing element in the buffer
* @_dp: The data parse cursor (updated before returning)
* @_len: Where to return the size of the element.
* @_errmsg: Where to return a pointer to an error message on error
*/
static int asn1_find_indefinite_length(const unsigned char *data, size_t datalen,
size_t *_dp, size_t *_len,
const char **_errmsg)
{
unsigned char tag, tmp;
size_t dp = *_dp, len, n;
int indef_level = 1;
next_tag:
if (unlikely(datalen - dp < 2)) {
if (datalen == dp)
goto missing_eoc;
goto data_overrun_error;
}
/* Extract a tag from the data */
tag = data[dp++];
if (tag == ASN1_EOC) {
/* It appears to be an EOC. */
if (data[dp++] != 0)
goto invalid_eoc;
if (--indef_level <= 0) {
*_len = dp - *_dp;
*_dp = dp;
return 0;
}
goto next_tag;
}
if (unlikely((tag & 0x1f) == ASN1_LONG_TAG)) {
do {
if (unlikely(datalen - dp < 2))
goto data_overrun_error;
tmp = data[dp++];
} while (tmp & 0x80);
}
/* Extract the length */
len = data[dp++];
if (len <= 0x7f)
goto check_length;
if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
/* Indefinite length */
if (unlikely((tag & ASN1_CONS_BIT) == ASN1_PRIM << 5))
goto indefinite_len_primitive;
indef_level++;
goto next_tag;
}
n = len - 0x80;
if (unlikely(n > sizeof(len) - 1))
goto length_too_long;
if (unlikely(n > datalen - dp))
goto data_overrun_error;
len = 0;
for (; n > 0; n--) {
len <<= 8;
len |= data[dp++];
}
check_length:
if (len > datalen - dp)
goto data_overrun_error;
dp += len;
goto next_tag;
length_too_long:
*_errmsg = "Unsupported length";
goto error;
indefinite_len_primitive:
*_errmsg = "Indefinite len primitive not permitted";
goto error;
invalid_eoc:
*_errmsg = "Invalid length EOC";
goto error;
data_overrun_error:
*_errmsg = "Data overrun error";
goto error;
missing_eoc:
*_errmsg = "Missing EOC in indefinite len cons";
error:
*_dp = dp;
return -1;
}
/**
* asn1_ber_decoder - Decoder BER/DER/CER ASN.1 according to pattern
* @decoder: The decoder definition (produced by asn1_compiler)
* @context: The caller's context (to be passed to the action functions)
* @data: The encoded data
* @datalen: The size of the encoded data
*
* Decode BER/DER/CER encoded ASN.1 data according to a bytecode pattern
* produced by asn1_compiler. Action functions are called on marked tags to
* allow the caller to retrieve significant data.
*
* LIMITATIONS:
*
* To keep down the amount of stack used by this function, the following limits
* have been imposed:
*
* (1) This won't handle datalen > 65535 without increasing the size of the
* cons stack elements and length_too_long checking.
*
* (2) The stack of constructed types is 10 deep. If the depth of non-leaf
* constructed types exceeds this, the decode will fail.
*
* (3) The SET type (not the SET OF type) isn't really supported as tracking
* what members of the set have been seen is a pain.
*/
int asn1_ber_decoder(const struct asn1_decoder *decoder,
void *context,
const unsigned char *data,
size_t datalen)
{
const unsigned char *machine = decoder->machine;
const asn1_action_t *actions = decoder->actions;
size_t machlen = decoder->machlen;
enum asn1_opcode op;
unsigned char tag = 0, csp = 0, jsp = 0, optag = 0, hdr = 0;
const char *errmsg;
size_t pc = 0, dp = 0, tdp = 0, len = 0;
int ret;
unsigned char flags = 0;
#define FLAG_INDEFINITE_LENGTH 0x01
#define FLAG_MATCHED 0x02
#define FLAG_LAST_MATCHED 0x04 /* Last tag matched */
#define FLAG_CONS 0x20 /* Corresponds to CONS bit in the opcode tag
* - ie. whether or not we are going to parse
* a compound type.
*/
#define NR_CONS_STACK 10
unsigned short cons_dp_stack[NR_CONS_STACK];
unsigned short cons_datalen_stack[NR_CONS_STACK];
unsigned char cons_hdrlen_stack[NR_CONS_STACK];
#define NR_JUMP_STACK 10
unsigned char jump_stack[NR_JUMP_STACK];
if (datalen > 65535)
return -EMSGSIZE;
next_op:
pr_debug("next_op: pc=\e[32m%zu\e[m/%zu dp=\e[33m%zu\e[m/%zu C=%d J=%d\n",
pc, machlen, dp, datalen, csp, jsp);
if (unlikely(pc >= machlen))
goto machine_overrun_error;
op = machine[pc];
if (unlikely(pc + asn1_op_lengths[op] > machlen))
goto machine_overrun_error;
/* If this command is meant to match a tag, then do that before
* evaluating the command.
*/
if (op <= ASN1_OP__MATCHES_TAG) {
unsigned char tmp;
/* Skip conditional matches if possible */
if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) ||
(op & ASN1_OP_MATCH__SKIP && dp == datalen)) {
flags &= ~FLAG_LAST_MATCHED;
pc += asn1_op_lengths[op];
goto next_op;
}
flags = 0;
hdr = 2;
/* Extract a tag from the data */
if (unlikely(datalen - dp < 2))
goto data_overrun_error;
tag = data[dp++];
if (unlikely((tag & 0x1f) == ASN1_LONG_TAG))
goto long_tag_not_supported;
if (op & ASN1_OP_MATCH__ANY) {
pr_debug("- any %02x\n", tag);
} else {
/* Extract the tag from the machine
* - Either CONS or PRIM are permitted in the data if
* CONS is not set in the op stream, otherwise CONS
* is mandatory.
*/
optag = machine[pc + 1];
flags |= optag & FLAG_CONS;
/* Determine whether the tag matched */
tmp = optag ^ tag;
tmp &= ~(optag & ASN1_CONS_BIT);
pr_debug("- match? %02x %02x %02x\n", tag, optag, tmp);
if (tmp != 0) {
/* All odd-numbered tags are MATCH_OR_SKIP. */
if (op & ASN1_OP_MATCH__SKIP) {
pc += asn1_op_lengths[op];
dp--;
goto next_op;
}
goto tag_mismatch;
}
}
flags |= FLAG_MATCHED;
len = data[dp++];
if (len > 0x7f) {
if (unlikely(len == ASN1_INDEFINITE_LENGTH)) {
/* Indefinite length */
if (unlikely(!(tag & ASN1_CONS_BIT)))
goto indefinite_len_primitive;
flags |= FLAG_INDEFINITE_LENGTH;
if (unlikely(2 > datalen - dp))
goto data_overrun_error;
} else {
int n = len - 0x80;
if (unlikely(n > 2))
goto length_too_long;
if (unlikely(n > datalen - dp))
goto data_overrun_error;
hdr += n;
for (len = 0; n > 0; n--) {
len <<= 8;
len |= data[dp++];
}
if (unlikely(len > datalen - dp))
goto data_overrun_error;
}
} else {
if (unlikely(len > datalen - dp))
goto data_overrun_error;
}
if (flags & FLAG_CONS) {
/* For expected compound forms, we stack the positions
* of the start and end of the data.
*/
if (unlikely(csp >= NR_CONS_STACK))
goto cons_stack_overflow;
cons_dp_stack[csp] = dp;
cons_hdrlen_stack[csp] = hdr;
if (!(flags & FLAG_INDEFINITE_LENGTH)) {
cons_datalen_stack[csp] = datalen;
datalen = dp + len;
} else {
cons_datalen_stack[csp] = 0;
}
csp++;
}
pr_debug("- TAG: %02x %zu%s\n",
tag, len, flags & FLAG_CONS ? " CONS" : "");
tdp = dp;
}
/* Decide how to handle the operation */
switch (op) {
case ASN1_OP_MATCH:
case ASN1_OP_MATCH_OR_SKIP:
case ASN1_OP_MATCH_ACT:
case ASN1_OP_MATCH_ACT_OR_SKIP:
case ASN1_OP_MATCH_ANY:
case ASN1_OP_MATCH_ANY_OR_SKIP:
case ASN1_OP_MATCH_ANY_ACT:
case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
case ASN1_OP_COND_MATCH_OR_SKIP:
case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
case ASN1_OP_COND_MATCH_ANY:
case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
case ASN1_OP_COND_MATCH_ANY_ACT:
case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
if (!(flags & FLAG_CONS)) {
if (flags & FLAG_INDEFINITE_LENGTH) {
size_t tmp = dp;
ret = asn1_find_indefinite_length(
data, datalen, &tmp, &len, &errmsg);
if (ret < 0)
goto error;
}
pr_debug("- LEAF: %zu\n", len);
}
if (op & ASN1_OP_MATCH__ACT) {
unsigned char act;
if (op & ASN1_OP_MATCH__ANY)
act = machine[pc + 1];
else
act = machine[pc + 2];
ret = actions[act](context, hdr, tag, data + dp, len);
if (ret < 0)
return ret;
}
if (!(flags & FLAG_CONS))
dp += len;
pc += asn1_op_lengths[op];
goto next_op;
case ASN1_OP_MATCH_JUMP:
case ASN1_OP_MATCH_JUMP_OR_SKIP:
case ASN1_OP_COND_MATCH_JUMP_OR_SKIP:
pr_debug("- MATCH_JUMP\n");
if (unlikely(jsp == NR_JUMP_STACK))
goto jump_stack_overflow;
jump_stack[jsp++] = pc + asn1_op_lengths[op];
pc = machine[pc + 2];
goto next_op;
case ASN1_OP_COND_FAIL:
if (unlikely(!(flags & FLAG_MATCHED)))
goto tag_mismatch;
pc += asn1_op_lengths[op];
goto next_op;
case ASN1_OP_COMPLETE:
if (unlikely(jsp != 0 || csp != 0)) {
pr_err("ASN.1 decoder error: Stacks not empty at completion (%u, %u)\n",
jsp, csp);
return -EBADMSG;
}
return 0;
case ASN1_OP_END_SET:
case ASN1_OP_END_SET_ACT:
if (unlikely(!(flags & FLAG_MATCHED)))
goto tag_mismatch;
/* fall through */
case ASN1_OP_END_SEQ:
case ASN1_OP_END_SET_OF:
case ASN1_OP_END_SEQ_OF:
case ASN1_OP_END_SEQ_ACT:
case ASN1_OP_END_SET_OF_ACT:
case ASN1_OP_END_SEQ_OF_ACT:
if (unlikely(csp <= 0))
goto cons_stack_underflow;
csp--;
tdp = cons_dp_stack[csp];
hdr = cons_hdrlen_stack[csp];
len = datalen;
datalen = cons_datalen_stack[csp];
pr_debug("- end cons t=%zu dp=%zu l=%zu/%zu\n",
tdp, dp, len, datalen);
if (datalen == 0) {
/* Indefinite length - check for the EOC. */
datalen = len;
if (unlikely(datalen - dp < 2))
goto data_overrun_error;
if (data[dp++] != 0) {
if (op & ASN1_OP_END__OF) {
dp--;
csp++;
pc = machine[pc + 1];
pr_debug("- continue\n");
goto next_op;
}
goto missing_eoc;
}
if (data[dp++] != 0)
goto invalid_eoc;
len = dp - tdp - 2;
} else {
if (dp < len && (op & ASN1_OP_END__OF)) {
datalen = len;
csp++;
pc = machine[pc + 1];
pr_debug("- continue\n");
goto next_op;
}
if (dp != len)
goto cons_length_error;
len -= tdp;
pr_debug("- cons len l=%zu d=%zu\n", len, dp - tdp);
}
if (op & ASN1_OP_END__ACT) {
unsigned char act;
if (op & ASN1_OP_END__OF)
act = machine[pc + 2];
else
act = machine[pc + 1];
ret = actions[act](context, hdr, 0, data + tdp, len);
if (ret < 0)
return ret;
}
pc += asn1_op_lengths[op];
goto next_op;
case ASN1_OP_MAYBE_ACT:
if (!(flags & FLAG_LAST_MATCHED)) {
pc += asn1_op_lengths[op];
goto next_op;
}
/* fall through */
case ASN1_OP_ACT:
ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len);
if (ret < 0)
return ret;
pc += asn1_op_lengths[op];
goto next_op;
case ASN1_OP_RETURN:
if (unlikely(jsp <= 0))
goto jump_stack_underflow;
pc = jump_stack[--jsp];
flags |= FLAG_MATCHED | FLAG_LAST_MATCHED;
goto next_op;
default:
break;
}
/* Shouldn't reach here */
pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n",
op, pc);
return -EBADMSG;
data_overrun_error:
errmsg = "Data overrun error";
goto error;
machine_overrun_error:
errmsg = "Machine overrun error";
goto error;
jump_stack_underflow:
errmsg = "Jump stack underflow";
goto error;
jump_stack_overflow:
errmsg = "Jump stack overflow";
goto error;
cons_stack_underflow:
errmsg = "Cons stack underflow";
goto error;
cons_stack_overflow:
errmsg = "Cons stack overflow";
goto error;
cons_length_error:
errmsg = "Cons length error";
goto error;
missing_eoc:
errmsg = "Missing EOC in indefinite len cons";
goto error;
invalid_eoc:
errmsg = "Invalid length EOC";
goto error;
length_too_long:
errmsg = "Unsupported length";
goto error;
indefinite_len_primitive:
errmsg = "Indefinite len primitive not permitted";
goto error;
tag_mismatch:
errmsg = "Unexpected tag";
goto error;
long_tag_not_supported:
errmsg = "Long tag not supported";
error:
pr_debug("\nASN1: %s [m=%zu d=%zu ot=%02x t=%02x l=%zu]\n",
errmsg, pc, dp, optag, tag, len);
return -EBADMSG;
}
EXPORT_SYMBOL_GPL(asn1_ber_decoder);
MODULE_LICENSE("GPL");
menuconfig ASYMMETRIC_KEY_TYPE
bool "Asymmetric (public-key cryptographic) key Support"
help
This option provides support for a key type that holds the data for
the asymmetric keys used for public key cryptographic operations such
as encryption, decryption, signature generation and signature
verification.
if ASYMMETRIC_KEY_TYPE
config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
bool "Asymmetric public-key crypto algorithm subtype"
help
This option provides support for asymmetric public key type handling.
If signature generation and/or verification are to be used,
appropriate hash algorithms (such as SHA-1) must be available.
ENOPKG will be reported if the requisite algorithm is unavailable.
config RSA_PUBLIC_KEY_PARSER
bool "RSA public key parser"
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select ASN1_DECODER
select ASN1_COMPILER
select OID_REGISTRY
help
This option provides support for parsing a blob containing RSA
public key data and provides the ability to instantiate a public
key.
config X509_CERTIFICATE_PARSER
bool "X.509 certificate parser"
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select ASN1_DECODER
select ASN1_COMPILER
select OID_REGISTRY
select LIB_DATE
help
This option provides support for parsing X.509 format blobs for key
data and provides the ability to instantiate a crypto key from a
public key packet found inside the certificate.
config PKCS7_MESSAGE_PARSER
bool "PKCS#7 message parser"
depends on X509_CERTIFICATE_PARSER
select ASN1_DECODER
select ASN1_COMPILER
select OID_REGISTRY
help
This option provides support for parsing PKCS#7 format messages for
signature data and provides the ability to verify the signature.
endif # ASYMMETRIC_KEY_TYPE
# SPDX-License-Identifier: GPL-2.0+
#
# Makefile for asymmetric cryptographic keys
#
obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := asymmetric_type.o
obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
#
# RSA public key parser
#
obj-$(CONFIG_RSA_PUBLIC_KEY_PARSER) += rsa_public_key.o
rsa_public_key-y := \
rsapubkey.asn1.o \
rsa_helper.o
$(obj)/rsapubkey.asn1.o: $(obj)/rsapubkey.asn1.c $(obj)/rsapubkey.asn1.h
$(obj)/rsa_helper.o: $(obj)/rsapubkey.asn1.h
#
# X.509 Certificate handling
#
obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
x509_key_parser-y := \
x509.asn1.o \
x509_akid.asn1.o \
x509_cert_parser.o \
x509_public_key.o
$(obj)/x509_cert_parser.o: \
$(obj)/x509.asn1.h \
$(obj)/x509_akid.asn1.h
$(obj)/x509.asn1.o: $(obj)/x509.asn1.c $(obj)/x509.asn1.h
$(obj)/x509_akid.asn1.o: $(obj)/x509_akid.asn1.c $(obj)/x509_akid.asn1.h
#
# PKCS#7 message handling
#
obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o
pkcs7_message-y := \
pkcs7.asn1.o \
pkcs7_parser.o
$(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h
$(obj)/pkcs7.asn1.o: $(obj)/pkcs7.asn1.c $(obj)/pkcs7.asn1.h
此差异已折叠。
PKCS7ContentInfo ::= SEQUENCE {
contentType ContentType ({ pkcs7_check_content_type }),
content [0] EXPLICIT SignedData OPTIONAL
}
ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID })
SignedData ::= SEQUENCE {
version INTEGER ({ pkcs7_note_signeddata_version }),
digestAlgorithms DigestAlgorithmIdentifiers,
contentInfo ContentInfo ({ pkcs7_note_content }),
certificates CHOICE {
certSet [0] IMPLICIT ExtendedCertificatesAndCertificates,
certSequence [2] IMPLICIT Certificates
} OPTIONAL ({ pkcs7_note_certificate_list }),
crls CHOICE {
crlSet [1] IMPLICIT CertificateRevocationLists,
crlSequence [3] IMPLICIT CRLSequence
} OPTIONAL,
signerInfos SignerInfos
}
ContentInfo ::= SEQUENCE {
contentType ContentType ({ pkcs7_note_OID }),
content [0] EXPLICIT Data OPTIONAL
}
Data ::= ANY ({ pkcs7_note_data })
DigestAlgorithmIdentifiers ::= CHOICE {
daSet SET OF DigestAlgorithmIdentifier,
daSequence SEQUENCE OF DigestAlgorithmIdentifier
}
DigestAlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }),
parameters ANY OPTIONAL
}
--
-- Certificates and certificate lists
--
ExtendedCertificatesAndCertificates ::= SET OF ExtendedCertificateOrCertificate
ExtendedCertificateOrCertificate ::= CHOICE {
certificate Certificate, -- X.509
extendedCertificate [0] IMPLICIT ExtendedCertificate -- PKCS#6
}
ExtendedCertificate ::= Certificate -- cheating
Certificates ::= SEQUENCE OF Certificate
CertificateRevocationLists ::= SET OF CertificateList
CertificateList ::= SEQUENCE OF Certificate -- This may be defined incorrectly
CRLSequence ::= SEQUENCE OF CertificateList
Certificate ::= ANY ({ pkcs7_extract_cert }) -- X.509
--
-- Signer information
--
SignerInfos ::= CHOICE {
siSet SET OF SignerInfo,
siSequence SEQUENCE OF SignerInfo
}
SignerInfo ::= SEQUENCE {
version INTEGER ({ pkcs7_note_signerinfo_version }),
sid SignerIdentifier, -- CMS variant, not PKCS#7
digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }),
authenticatedAttributes CHOICE {
aaSet [0] IMPLICIT SetOfAuthenticatedAttribute
({ pkcs7_sig_note_set_of_authattrs }),
aaSequence [2] EXPLICIT SEQUENCE OF AuthenticatedAttribute
-- Explicit because easier to compute digest on
-- sequence of attributes and then reuse encoded
-- sequence in aaSequence.
} OPTIONAL,
digestEncryptionAlgorithm
DigestEncryptionAlgorithmIdentifier ({ pkcs7_sig_note_pkey_algo }),
encryptedDigest EncryptedDigest,
unauthenticatedAttributes CHOICE {
uaSet [1] IMPLICIT SET OF UnauthenticatedAttribute,
uaSequence [3] IMPLICIT SEQUENCE OF UnauthenticatedAttribute
} OPTIONAL
} ({ pkcs7_note_signed_info })
SignerIdentifier ::= CHOICE {
-- RFC5652 sec 5.3
issuerAndSerialNumber IssuerAndSerialNumber,
subjectKeyIdentifier [0] IMPLICIT SubjectKeyIdentifier
}
IssuerAndSerialNumber ::= SEQUENCE {
issuer Name ({ pkcs7_sig_note_issuer }),
serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial })
}
CertificateSerialNumber ::= INTEGER
SubjectKeyIdentifier ::= OCTET STRING ({ pkcs7_sig_note_skid })
SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute
AuthenticatedAttribute ::= SEQUENCE {
type OBJECT IDENTIFIER ({ pkcs7_note_OID }),
values SET OF ANY ({ pkcs7_sig_note_authenticated_attr })
}
UnauthenticatedAttribute ::= SEQUENCE {
type OBJECT IDENTIFIER,
values SET OF ANY
}
DigestEncryptionAlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }),
parameters ANY OPTIONAL
}
EncryptedDigest ::= OCTET STRING ({ pkcs7_sig_note_signature })
---
--- X.500 Name
---
Name ::= SEQUENCE OF RelativeDistinguishedName
RelativeDistinguishedName ::= SET OF AttributeValueAssertion
AttributeValueAssertion ::= SEQUENCE {
attributeType OBJECT IDENTIFIER ({ pkcs7_note_OID }),
attributeValue ANY
}
此差异已折叠。
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* PKCS#7 crypto data parser internal definitions
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*/
#include <linux/oid_registry.h>
#include <crypto/pkcs7.h>
#include "x509_parser.h"
#define kenter(FMT, ...) \
pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) \
pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
struct pkcs7_signed_info {
struct pkcs7_signed_info *next;
struct x509_certificate *signer; /* Signing certificate (in msg->certs) */
unsigned index;
bool unsupported_crypto; /* T if not usable due to missing crypto */
bool blacklisted;
/* Message digest - the digest of the Content Data (or NULL) */
const void *msgdigest;
unsigned msgdigest_len;
/* Authenticated Attribute data (or NULL) */
unsigned authattrs_len;
const void *authattrs;
unsigned long aa_set;
#define sinfo_has_content_type 0
#define sinfo_has_signing_time 1
#define sinfo_has_message_digest 2
#define sinfo_has_smime_caps 3
#define sinfo_has_ms_opus_info 4
#define sinfo_has_ms_statement_type 5
time64_t signing_time;
/* Message signature.
*
* This contains the generated digest of _either_ the Content Data or
* the Authenticated Attributes [RFC2315 9.3]. If the latter, one of
* the attributes contains the digest of the the Content Data within
* it.
*
* THis also contains the issuing cert serial number and issuer's name
* [PKCS#7 or CMS ver 1] or issuing cert's SKID [CMS ver 3].
*/
struct public_key_signature *sig;
};
struct pkcs7_message {
struct x509_certificate *certs; /* Certificate list */
struct x509_certificate *crl; /* Revocation list */
struct pkcs7_signed_info *signed_infos;
u8 version; /* Version of cert (1 -> PKCS#7 or CMS; 3 -> CMS) */
bool have_authattrs; /* T if have authattrs */
/* Content Data (or NULL) */
enum OID data_type; /* Type of Data */
size_t data_len; /* Length of Data */
size_t data_hdrlen; /* Length of Data ASN.1 header */
const void *data; /* Content Data (or 0) */
};
此差异已折叠。
此差异已折叠。
RsaPubKey ::= SEQUENCE {
n INTEGER ({ rsa_get_n }),
e INTEGER ({ rsa_get_e })
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -7,3 +7,4 @@ obj-y += hexdump.o
obj-y += lmb.o
obj-y += string.o
obj-$(CONFIG_ERRNO_STR) += test_errno_str.o
obj-$(CONFIG_UT_LIB_ASN1) += asn1.o
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册