⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sps_dve.c

📁 RMI的处理器au1200系列所用的BOOTLOAD,包括SD卡启动USB启动硬盘启动网络启动,并初始化硬件的所有参数,支持内核调试.
💻 C
字号:
/** * @file sps_dve.c * SPS module for decryption and signature verfication *  (dve = decryption and verification engine :-) * * @version $Revision$ $State$ * * @date @(#) Sep 30 2004, 21:24:01 * * @author Reinhard Wobst * *****************************************************************************//* * Copyright 2002 ADVANCED MICRO DEVICES, INC. All Rights Reserved. * * This software and any related documentation (the "Materials") are the * confidential proprietary information of AMD. Unless otherwise provided * in an agreement specifically licensing the Materials, the Materials are * provided in confidence and may not to be used, distributed, modified, or * reproduced in whole or in part by any means. * * LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY * EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO * WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY * PARTICULAR PURPOSE, OR WARRANTIES ARISING FORM CONDUCT, COURSE OF * DEALING, OR USAGE OF TRADE.  IN NO EVENT SHALL AMD OR ITS LICENSORS BE * LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, * DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF * INFORMATION) ARISING OUT OF THE USE OF OR INABILITY TO USE THE * MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES.  BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION OR * LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE * ABOVE LIMITATION MAY NOT APPLY TO YOU. * * AMD does not assume any responsibility for any errors which may appear * in the Materials nor any responsibility to support or update the * Materials.  AMD retains the right to modify the Materials at any time, * without notice, and is not obligated to provide such modified Materials * to you. * * NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make * any further information, software, technical information, know-how, or * show-how available to you. * *//******************************************************************************  Defines and includes*****************************************************************************/#include "sec.h"#include "debug.h"/* standard interfaces */#include <string.h>#include <stdlib.h>#include <stdio.h>#if STANDALONE == 0    /* Firmware interfaces */#include "sec.h"#include "ssfif.h"#endif#include "conf.h"#include "dve_api.h"#include "modules.h"#include "debug.h"#ifdef MSDOS#include "bn.h"#include "aes_api.h"#include "sha1.h"#else#include "Bn/bn.h"#include "Aes/aes_api.h"#include "Sha/sha1.h"#endif/******************************************************************************  Data*****************************************************************************/static struct MY_WORKSPACE *wsp;static int key_select[NUMSIG];static int my_first;/******************************************************************************  local function declarations*****************************************************************************/static void dve_sigstore(unsigned char *header);static unsigned char *sps_compose(const unsigned char part[16]);/******************************************************************************  global interface*****************************************************************************//** * @brief       initialize symmetric decryption/verification * * allocate SHA context, decrypt session key, set IV, compute round keys, * set my_first to 1 (used in dve_process()) * * @param iv        initialization vector of length MY_BLOCKSIZE/8 * @param cipertext at least MY_HEADSIZE bytes of ciphertext - see *          conf.h (not checked!) * @param workspace pointer to workspace structure */void dve_init(unsigned char *ciphertext,	      unsigned char *iv, struct MY_WORKSPACE *workspace){    unsigned char lociv[MY_KEYSIZE / 8], start;    static unsigned char fixedkey[MY_KEYSIZE / 8];    const static unsigned char const_part[16] = {	'w', 'h', 'i', 't',	'e', 'h', 'o', 'r',	's', 'e', 'e', 'd',	'u', 'c', 'a', 't',    };    int n, alt;    DP0(("*** Initialization"));    my_first = 1;    wsp = workspace;    memcpy(workspace->AesOfbDecryptIv, iv, MY_BLOCKSIZE / 8);    /* initialize NUMSIG SHA1 instances and diversify them */    for (n = NUMSIG; n--;) {	SHA1Init(wsp->sha1_ctx + n);	start = n & 0xff;	SHA1Update(wsp->sha1_ctx + n, &start, 1);    }    /* initialize symmetric OFB decryption */    for (alt = 0, n = MY_KEYSIZE / 8; n--;)	alt |= iv[n];    if (!alt)	for (n = MY_KEYSIZE / 8; n--;)	    fixedkey[n] = n & 0xff;    memcpy(lociv, iv, sizeof(lociv));    /* initialise AES module with IV to decrypt Session Key */    decrypt_aes_init(alt ? sps_compose(const_part) : fixedkey, lociv,		     &(wsp->Rkeys));    /* decrypt SK from ESK */    decrypt_aes_ofb(ciphertext, MY_KEYSIZE / 8);#if SPS_VERBOSE == 1    DP0(("master key: "));    for (n = 0; n < MY_KEYSIZE / 8; ++n)	DP0(("%02x", (alt ? sps_compose(const_part) : fixedkey)[n]));    DP0(("\n"));    DP0(("session key: "));    for (n = 0; n < MY_KEYSIZE / 8; ++n)	DP0(("%02x", ciphertext[n]));    DP0(("\n"));#endif    /* reinitialise AES module with SK for further decryption operations */    decrypt_aes_init(ciphertext, workspace->AesOfbDecryptIv,		     &(wsp->Rkeys));}/* ------------------------------------------------------------------ *//** * @brief routine which decrypts a data field encrypted with AES_128_OFB * * On first call (recognized by non-zero value of file-global variable * my_first), NUMSIG signatures and the following byte (for public key * selection) are read and stored after decryption. They are returned, * you have to skip them "by hand"! (the offset is MY_HEADSIZE) * * Hash computation is done background. * * @param cipherplaintext   [in,out] ciphertext buffer, will be *                   overwritten with plaintext * @param len           [in ]    # of bytes for in and output * * @return *      MY_PARMERR  len < MY_HEADSIZE on first call, *              len <= 0 on some following call *      number of decrypted bytes else * */int dve_process(unsigned char *cipherplaintext, int len,		SpsIntegrCheckMode_t IntCheckMode){    int m, n, ret;    DP0(("dve_process: %d bytes to decrypt", len));    /* store signatures and compute keyselect field */    if (my_first) {	if (len < MY_HEADSIZE)	    return MY_PARMERR;	my_first = 0;	/* for snowmass secure boot the signatures will not be encrypted! */	if (IntCheckMode == SPS_ENCRYPT_SIGNED) {	    decrypt_aes_ofb(cipherplaintext + MY_SIGOFF, len - MY_SIGOFF);	}	/* we check, if the three alignment bytes are 0, as expected.	 * if not - we have a decrypt error	 */	m = cipherplaintext[MY_HEADSIZE - 3];	m += cipherplaintext[MY_HEADSIZE - 2];	m += cipherplaintext[MY_HEADSIZE - 1];	if (m != 0) {	    DP0(("dve_process: decrypt error %02x\n", m));	    return MY_PARMERR;	}	/* store signatures and key select info in workspace */	/* starts @ session key offset */	dve_sigstore(cipherplaintext + MY_SIGOFF);	/* for including key_sel in hash adapt following calculations as to leave key_sel for SHA1Update below... */	/* replace all MY_HEADSIZE with (MY_HEADSIZE-(sizeof(key_sel) + sizeof(align))) */	cipherplaintext += MY_HEADSIZE;	len -= MY_HEADSIZE;	/* set len to zero to avoid SHA1 processing below.... */    } else {	if (len <= 0)	    return MY_PARMERR;	/* for snowmass secure boot first hash then decrypt! */	if (IntCheckMode == SPS_ENCRYPT_SIGNED) {	    decrypt_aes_ofb(cipherplaintext, len);	}    }    ret = len;    /* the included SHA1 implementation destroys the buffer, so we have     * to copy it and hash in portions     */    /* this will not fire for the PatchInfo field as len is asigned zero above... */    while (len > 0) {	n = sizeof(wsp->scratchbuf);	if (len < sizeof(wsp->scratchbuf))	    n = len;	for (m = NUMSIG; m--;) {	    memcpy(wsp->scratchbuf, cipherplaintext, n);	    SHA1Update(wsp->sha1_ctx + m, wsp->scratchbuf, n);	}	/* for snowmass secure boot first hash then decrypt! */	/* todo mgrell: review/test this construct for different length for streaming capabilities!: */	/* in original hss AES"de"crypt was done on entire block, here we do it in scratchbuf size manner... */	if (IntCheckMode == SPS_SIGN_ENCRYPTED) {	    decrypt_aes_ofb(cipherplaintext, n);	}	cipherplaintext += n;	len -= n;    }    return ret;}/* ------------------------------------------------------------------ *//** * @brief   store NUMSIG signatures, compute key numbers * * The select byte after the signatures is used to compute the * field key_select[NUMSIG] that determines which public keys * are used for encryption (and which signatures have to be skipped; * these values of key_select[] are negative). * * Structure of the select_byte: * * Bit 0  1  2  3  4  5  6  7 *     key0  key1  key2  exclude * * The key number 0...3 of key0 selects one key among keys 0...3, * key1 selects 4...7, and key2 selects 8...11. * If the 'exclude' bits are zero, all three fields are valid. * Otherwise, for values 1...3 the key0...key2 has to be skipped, * respectively. */static void dve_sigstore(unsigned char *header){    const unsigned char mask = 03;    int n, select_byte;    select_byte = header[NUMSIG * MY_SIGSIZE / 8];    for (n = 0; n < NUMSIG; ++n, select_byte >>= 2) {	memcpy((wsp->sigbuf)[n], header + n * MY_SIGSIZE / 8,	       MY_SIGSIZE / 8);	key_select[n] = (int) (select_byte & mask) + (n << 2);    }    /* check for deactivated field */    if (select_byte &= mask)	key_select[select_byte - 1] = -1;}/* ------------------------------------------------------------------ *//** * @brief   check signatures: compute final hashes, test against sigbuf * * @return *      MY_SIGFAIL  signature failed *      MY_ERR      some internal operation failed *      MY_OK       else */int dve_sigcheck(){    unsigned char cmpsig[MY_SIGSIZE / 8 + 1];	/* maybe, "...+1" is not necessary */    unsigned char hash1[MY_HASHSIZE / 8];    int n, len, signr, keynr, ret;    BN_CTX *ctx;    BIGNUM *mod, *bnsign, *pubex;    ret = MY_OK;    mod = NULL;    bnsign = NULL;    pubex = NULL;    /* compute hash over decrypted text */    for (n = NUMSIG; n--;)	SHA1Final(wsp->Hash[n], wsp->sha1_ctx + n);#if SPS_VERBOSE == 1    {	int k;	for (k = 0; k < NUMSIG; ++k) {	    DP0(("Hash %d:", k + 1));	    for (n = 0; n < MY_HASHSIZE / 8; ++n) {		DP0(("%02x ", wsp->Hash[k][n]));		if (n % 10 == 9)		    DP0(("\n"));	    }	    DP0(("\n"));	}    }#endif    /* create bignum context */    ctx = BN_CTX_new();    if (ctx == NULL)	return MY_ERR;    /* *** check signatures */    for (signr = 0; signr < NUMSIG; ++signr) {	if ((keynr = key_select[signr]) < 0)	    continue;		/* deselected field */	/* Cannabis part: hashhash */	SHA1Init(wsp->sha1_ctx);	SHA1Update(wsp->sha1_ctx, wsp->Hash[signr], MY_HASHSIZE / 8);	SHA1Final(hash1, wsp->sha1_ctx);	bnsign = pubex = mod = NULL;	/* convert modulus */	mod = BN_bin2bn(Modulus[keynr], sizeof(Modulus[keynr]), NULL);	DP0(("modulus %d converted", keynr));	if (mod == NULL) {	    ret = MY_ERR;	    break;	}	/* convert public exponent */	pubex = BN_bin2bn(publicExponent[keynr],			  sizeof(publicExponent[keynr]), NULL);	DP0(("public exponent %d converted", keynr));	if (pubex == NULL) {	    ret = MY_ERR;	    break;	}	/* convert signature */	bnsign = BN_bin2bn((wsp->sigbuf)[signr], MY_SIGSIZE / 8, NULL);	if (bnsign == NULL) {	    ret = MY_ERR;	    break;	}	/* public encrypt */	BN_mod_exp(bnsign, bnsign, pubex, mod, ctx);	len = BN_bn2bin(bnsign, cmpsig);	if (memcmp	    (hash1, cmpsig + MY_SIGSIZE / 8 - 1 - MY_HASHSIZE / 8,	     MY_HASHSIZE / 8)) {	    ret = MY_SIGFAIL;	    break;	}	DP0(("--> signature %d verified successfully", signr));	BN_free(bnsign);	BN_free(pubex);	BN_free(mod);    }    BN_CTX_free(ctx);    if (ret != MY_OK) {	if (bnsign != NULL)	    BN_free(bnsign);	if (pubex != NULL)	    BN_free(pubex);	if (mod != NULL)	    BN_free(mod);    }    return ret;}/* ------------------------------------------------------------------ *//** * @brief   provide workspace for bignum library * * @param requ_size size of block, can be at most sizeof(BIGNUM)*32 *          where the macro TABLE_SIZE defined as 32 in *          bn/bn_exp.c is used (dirty, but with least *          code modification) */BIGNUM *sps_dve_get_valbuf(int requ_size){    if (requ_size <= sizeof(BIGNUM) * 32) {	return &(wsp->bn_buf[0]);    }    SsfFatalError(1);    return NULL;		/* dummy, for supressing compiler warning only */}/* ------------------------------------------------------------------ *//** * @brief   generate a 16 byte data array * * @param */unsigned char *sps_compose(const unsigned char part[16]){#ifdef PATCH_SYSTEM_WITH_TEST_KEYS#ifndef MSDOS#warning using test symmetric keys#endif    static unsigned char mykey[16] = {	0x5f, 0x44, 0x3a, 0x23,	0x5c, 0xc7, 0x5a, 0xbb,	0xdf, 0xbc, 0x97, 0xf2,	0xa9, 0xef, 0xa9, 0x51    };#else#warning using secure symmetric keys    unsigned char *p, *q;    int n;    static unsigned char mykey[16] = {	'i', 'o', 'n', 'S',	'c', 'h', 'i', 'm',	'm', 'e', 'l', 'b',	'i', 'l', 'd', 'g',    };    for (n = 16, p = &mykey[0], q = (unsigned char *) &part[0]; n--;) {	*p++ ^= *q++;    }#endif#ifdef USE_TDDFW_ENVIRONMENT    return get_key();#else    return mykey;#endif}static const unsigned char localaeskeywhichisnotsecurehere[] = {    0x5f, 0x44, 0x3a, 0x23, 0x5c, 0xc7, 0x5a, 0xbb, 0xdf, 0xbc, 0x97, 0xf2,	0xa9, 0xef, 0xa9, 0x51};unsigned char *get_key(){    return (unsigned char *) localaeskeywhichisnotsecurehere;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -