/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ /* * drivers/storagekey/storagekey.c * * Copyright (C) 2020 Amlogic, Inc. All rights reserved. * */ /* extern from bl31 */ /* * when RET_OK * query: retval=1: key exsit,=0: key not exsit; * tell: retvak = key size * status: retval=1: secure, retval=0: non-secure */ #include #include #include #include #include #ifdef CONFIG_STORE_COMPATIBLE #include #endif /* key buffer status */ /* bit0, dirty flag*/ #define KEYBUFFER_CLEAN (0 << 0) #define KEYBUFFER_DIRTY (1 << 0) #define SECUESTORAGE_HEAD_SIZE (256) #define SECUESTORAGE_WHOLE_SIZE (0x40000) struct storagekey_info_t { uint8_t * buffer; uint32_t size; uint32_t status; }; static struct storagekey_info_t storagekey_info = { .buffer = NULL, /* default size */ .size = SECUESTORAGE_WHOLE_SIZE, .status = KEYBUFFER_CLEAN, }; /** *1.init * return ok 0, fail 1 */ int32_t amlkey_init(uint8_t *seed, uint32_t len, int encrypt_type) { int32_t ret = 0; uint32_t buffer_size, actual_size; /* do nothing for now*/ printf("%s() enter!\n", __func__); if (storagekey_info.buffer != NULL) { printf("%s() %d: already init!\n", __func__, __LINE__); goto _out; } /* get buffer from bl31 */ storagekey_info.buffer = secure_storage_getbuffer(&buffer_size); if (storagekey_info.buffer == NULL) { printf("%s() %d: can't get buffer from bl31!\n", __func__, __LINE__); ret = -1; goto _out; } if (encrypt_type == -1) encrypt_type = 0; secure_storage_set_enctype(encrypt_type); /* full fill key infos from storage. */ ret = store_key_read(storagekey_info.buffer, storagekey_info.size, &actual_size); if (ret) { /* memset head info for bl31 */ memset(storagekey_info.buffer, 0, SECUESTORAGE_HEAD_SIZE); ret = 0; goto _out; } storagekey_info.size = actual_size; secure_storage_notifier_ex(actual_size, 0); storagekey_info.buffer = secure_storage_getbuffer(&buffer_size); if (buffer_size != actual_size) { ret = -1; goto _out; } #ifdef CONFIG_STORE_COMPATIBLE info_disprotect &= ~DISPROTECT_KEY; //protect #endif _out: return ret; } /** *2. query if the key already programmed * return: exsit 1, non 0 */ int32_t amlkey_isexsit(const uint8_t * name) { int32_t ret = 0; uint32_t retval; if ( NULL == name ) { printf("%s() %d, invalid key ", __func__, __LINE__); return 0; } ret = secure_storage_query((uint8_t *)name, &retval); if (ret) { printf("%s() %d: ret %d\n", __func__, __LINE__, ret); retval = 0; } return (int32_t)retval; } static int32_t amlkey_get_attr(const uint8_t * name) { int32_t ret = 0; uint32_t retval; if ( NULL == name ) { printf("%s() %d, invalid key ", __func__, __LINE__); return 0; } ret = secure_storage_status((uint8_t *)name, &retval); if (ret) { printf("%s() %d: ret %d\n", __func__, __LINE__, ret); retval = 0; } return (int32_t)(retval); } /** * 3.1 query if the programmed key is secure. key must exsit! * return secure 1, non 0; */ int32_t amlkey_issecure(const uint8_t * name) { return (amlkey_get_attr(name)&UNIFYKEY_ATTR_SECURE_MASK); } /** * 3.2 query if the programmed key is encrypt * return encrypt 1, non-encrypt 0; */ int32_t amlkey_isencrypt(const uint8_t * name) { return (amlkey_get_attr(name)&UNIFYKEY_ATTR_ENCRYPT_MASK); } /** * 4. actual bytes of key value * return actual size. */ ssize_t amlkey_size(const uint8_t *name) { ssize_t size = 0; int32_t ret = 0; uint32_t retval; if ( NULL == name ) { printf("%s() %d, invalid key ", __func__, __LINE__); return 0; } ret = secure_storage_tell((uint8_t *)name, &retval); if (ret) { printf("%s() %d: ret %d\n", __func__, __LINE__, ret); retval = 0; } size = (ssize_t)retval; return size; } /** *5. read non-secure key in bytes, return bytes readback actually. * return actual size read back. */ ssize_t amlkey_read(const uint8_t *name, uint8_t *buffer, uint32_t len) { int32_t ret = 0; ssize_t retval = 0; uint32_t actual_len; if ( NULL == name ) { printf("%s() %d, invalid key ", __func__, __LINE__); return 0; } ret = secure_storage_read((uint8_t *)name, buffer, len, &actual_len); if (ret) { printf("%s() %d: return %d\n", __func__, __LINE__, ret); retval = 0; goto _out; } retval = actual_len; _out: return retval; } /** * 6.write secure/non-secure key in bytes , return bytes readback actually * attr: bit0, secure/non-secure; * bit8, encrypt/non-encrypt; * return actual size write down. */ ssize_t amlkey_write(const uint8_t *name, uint8_t *buffer, uint32_t len, uint32_t attr) { int32_t ret = 0; ssize_t retval = 0; uint32_t actual_size; if ( NULL == name ) { printf("%s() %d, invalid key ", __func__, __LINE__); return retval; } ret = secure_storage_write((uint8_t *)name, buffer, len, attr); if (ret) { printf("%s() %d: return %d\n", __func__, __LINE__, ret); retval = 0; goto _out; } else { retval = (ssize_t)len; /* write down! */ if (storagekey_info.buffer != NULL) { ret = store_key_write(storagekey_info.buffer, storagekey_info.size, &actual_size); if (ret) { printf("%s() %d, store_key_write fail\n", __func__, __LINE__); retval = 0; } } } _out: return retval; } /** * 7. get the hash value of programmed secure key | 32bytes length, sha256 * return success 0, fail -1 */ int32_t amlkey_hash_4_secure(const uint8_t * name, uint8_t * hash) { int32_t ret = 0; ret = secure_storage_verify((uint8_t *)name, hash); return ret; } /** * 7. del key by name * return success 0, fail -1 */ int32_t amlkey_del(const uint8_t * name) { int32_t ret = 0; uint32_t actual_size; ret = secure_storage_remove((uint8_t *)name); if ((ret == 0) && (storagekey_info.buffer != NULL)) { /* flush back */ ret = store_key_write(storagekey_info.buffer, storagekey_info.size, &actual_size); if (ret) { printf("%s() %d, store_key_write fail\n", __func__, __LINE__); } } else { printf("%s() %d, remove key fail\n", __func__, __LINE__); } return ret; }