diff --git a/android/wolfssljni-ndk-gradle/app/CMakeLists.txt b/android/wolfssljni-ndk-gradle/app/CMakeLists.txt index 94df6162a..5f80a4338 100644 --- a/android/wolfssljni-ndk-gradle/app/CMakeLists.txt +++ b/android/wolfssljni-ndk-gradle/app/CMakeLists.txt @@ -59,10 +59,14 @@ if ("${WOLFSSL_PKG_TYPE}" MATCHES "normal") -DWOLFSSL_AKID_NAME -DHAVE_CTS -DNO_DES3 -DGCM_TABLE_4BIT -DTFM_TIMING_RESISTANT -DECC_TIMING_RESISTANT -DHAVE_AESGCM -DSIZEOF_LONG=4 -DSIZEOF_LONG_LONG=8 + + -DHAVE_SECURE_RENEGOTIATION + #-DHAVE_SERVER_RENEGOTIATION_INFO + -DWOLFSSL_ALT_CERT_CHAINS # Defines added for debugging. These can be removed if debug logging is not needed # and will increase performance and reduce library footprint size if removed. - -DEBUG_WOLFSSL + -DEBUG_WOLFSSL -DWOLFSSL_ANDROID_DEBUG # Defines added for wolfCrypt test and benchmark only, may not be needed for your # own application. @@ -272,8 +276,8 @@ target_link_libraries( # --------------------------- wolfCrypt CryptoCb Source Files -------------------------------------- # set which cryptocb subsystem (if any) will be used -set(WOLFSSL_CRYPTOCB_TYPE "") -#set(WOLFSSL_CRYPTOCB_TYPE "ccb_vaultic") +#set(WOLFSSL_CRYPTOCB_TYPE "") +set(WOLFSSL_CRYPTOCB_TYPE "ccb_vaultic") # Support for ccb_vaultic if("${WOLFSSL_CRYPTOCB_TYPE}" MATCHES "ccb_vaultic") @@ -288,6 +292,9 @@ if("${WOLFSSL_CRYPTOCB_TYPE}" MATCHES "ccb_vaultic") add_library(ccbvaultic SHARED ${cryptocb_DIR}/ccb_vaultic.c) + add_library(ccbvaulticjni SHARED + ${cryptocb_DIR}/com_wolfssl_ccbvaultic_ccbVaultic.c) + # TODO Add support for other architectures if("${ANDROID_ABI}" MATCHES "arm64-v8a") add_definitions( @@ -295,8 +302,8 @@ if("${WOLFSSL_CRYPTOCB_TYPE}" MATCHES "ccb_vaultic") #-DCCBVAULTIC_NO_AES #-DCCBVAULTIC_NO_RSA -DCCBVAULTIC_NO_SHA - #-DCCBVAULTIC_DEBUG - #-DCCBVAULTIC_DEBUG_TIMING + -DCCBVAULTIC_DEBUG + -DCCBVAULTIC_DEBUG_TIMING ) set(VAULTIC_DIR ${cryptocb_DIR}/VaultIC-TLS_420/vaultic_tls-4xx) @@ -336,4 +343,10 @@ if("${WOLFSSL_CRYPTOCB_TYPE}" MATCHES "ccb_vaultic") wolfssljni ccbvaultic ) + # Link ccbvaulticjni to ccbvaultic + target_link_libraries( + ccbvaulticjni + ccbvaultic + ) + endif() #ccb_vaultic diff --git a/android/wolfssljni-ndk-gradle/app/build.gradle b/android/wolfssljni-ndk-gradle/app/build.gradle index 52fc94ca0..bfe17e1ff 100644 --- a/android/wolfssljni-ndk-gradle/app/build.gradle +++ b/android/wolfssljni-ndk-gradle/app/build.gradle @@ -32,6 +32,8 @@ android { sourceSets { // wolfSSL JNI Java source files are added here main.java.srcDirs += '../wolfssljni/src/java' + // ccbVaultIc JNI Java source files + main.java.srcDirs += '../../../ccb_vaultic/java' } namespace 'com.wolfssl.wolfssljni_ndk_gradle' } diff --git a/android/wolfssljni-ndk-gradle/app/src/main/java/com/wolfssl/wolfssljni_ndk_gradle/MainActivity.java b/android/wolfssljni-ndk-gradle/app/src/main/java/com/wolfssl/wolfssljni_ndk_gradle/MainActivity.java index b18a4533c..640928f02 100644 --- a/android/wolfssljni-ndk-gradle/app/src/main/java/com/wolfssl/wolfssljni_ndk_gradle/MainActivity.java +++ b/android/wolfssljni-ndk-gradle/app/src/main/java/com/wolfssl/wolfssljni_ndk_gradle/MainActivity.java @@ -7,15 +7,22 @@ import android.widget.TextView; import com.wolfssl.WolfSSL; +import com.wolfssl.provider.jsse.WolfSSLKeyX509; import com.wolfssl.provider.jsse.WolfSSLProvider; +import com.wolfssl.ccbvaultic.ccbVaultIc; + import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; +import java.security.KeyStore; import java.security.Security; import java.util.concurrent.Executors; +import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; public class MainActivity extends AppCompatActivity { @@ -76,11 +83,34 @@ private void appendDisplayText(String s) }); }; + String[] filenames = {"/key.pem","/crt.pem",null}; //"/ca.pem" + + byte[] debugPin = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; + + byte[] debugMac = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; + byte[] debugEnc = { 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F}; + + + byte[] debugKey = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F}; + byte[] debugLabel = "Debug Label".getBytes(); + + byte[] debugFile1 = "FILE1".getBytes(); + byte[] debugFile2 = "FILE2".getBytes(); + + + public String getCmd = "GET / HTTP/1.1\r\n" + + "Host: www.wolfssl.com\r\n" + + "Accept: */*\r\n\r\n"; + private final View.OnClickListener sslSocketConnectListener = v -> { - setDisplayText("Making simple SSL/TLS connection to:\n" + + setDisplayText("Making simple SSL/TLS connection to:" + host + ":" + port + "\n" + - "See logcat output for details (adb logcat).\n" + - "...\n"); + "See logcat output for details (adb logcat).\n"); Executors.newSingleThreadExecutor().execute(() -> { try { /* Enable wolfJSSE debug messages */ @@ -88,11 +118,16 @@ private void appendDisplayText(String s) /* Select The devId which will be registered and used on every other invocation */ /* Unique devId's are compiled into wolfssljni */ - //int devId = 0x56490420; /* VaultIC 420 */ - int devId = WolfSSL.INVALID_DEVID; /* No hardware offload */ + int devId = 0x56490420; /* VaultIC 420 */ + //int devId = WolfSSL.INVALID_DEVID; /* No hardware offload */ /* Select if the cipher suites and protocols will be limited */ - boolean limitCipherProtocol = false; + boolean limitCipherProtocol = true; + //boolean limitCipherProtocol = false; + + /* Select if using Debug or KDF user for HW provisioning and connection */ + boolean useKdfUser = true; + //boolean useKdfUser = false; long[] ts = new long[10]; @@ -104,70 +139,163 @@ private void appendDisplayText(String s) ts[1] = System.currentTimeMillis(); connectCount++; - if (((connectCount % 2) == 0) && (devId != WolfSSL.INVALID_DEVID)) { - appendDisplayText("B. Using hardware offload\n"); - wolfProv.registerDevId(devId); - wolfProv.setDevId(devId); - } else { - appendDisplayText("B. Using software crypto.\n"); + KeyManager[] km = null; + TrustManager[] tm = null; + long totalRead = 0; + ccbVaultIc cv = new ccbVaultIc(); + + if(devId != WolfSSL.INVALID_DEVID) { + switch(connectCount % 3) { + case 1: //SW + { + appendDisplayText("B. Using software crypto.\n"); + wolfProv.setDevId(WolfSSL.INVALID_DEVID); + };break; + case 2: //HW Manu + { + appendDisplayText("B. Using hardware offload - MANU\n"); + + // MANU + cv.UpdateDefaultAuth_Manu(debugPin); + + wolfProv.registerDevId(devId); + wolfProv.setDevId(devId); + + int rc = 0; + if(useKdfUser) { + rc = cv.ProvisionAction_App( + devId, Boolean.TRUE, + debugKey, debugLabel, + filenames[0], debugFile1, + filenames[1], debugFile2, + null, null); + } else { + rc = cv.ProvisionAction_Debug( + devId, Boolean.TRUE, + debugMac, debugEnc, + filenames[0], debugFile1, + filenames[1], debugFile2, + null, null); + } + appendDisplayText("Provision rc=" + rc + "\n" ); + byte[] data = new byte[ccbVaultIc.CCBVAULTIC_INFO_LEN]; + rc = cv.GetInfoText(devId, data); + appendDisplayText("GetInfoText rc=" + rc + "\n" + new String(data)); + + rc = cv.PerformSelfTest(devId); + appendDisplayText("SelfTest rc=" + rc + "\n"); + // Skip the connection tests + };break; + case 0: //HW App + { + appendDisplayText("B. Using hardware offload - APP\n"); + + if(useKdfUser) { + cv.UpdateDefaultAuth_App(debugKey, debugLabel); + } else { + cv.UpdateDefaultAuth_Debug(debugMac, debugEnc); + } + + wolfProv.registerDevId(devId); + wolfProv.setDevId(devId); + + //Load static data + //km = cv.GenerateKM(medKeyFile.getBytes(), medCrtFile.getBytes()); + + //Load data from VaultIC + ccbVaultIc.LoadFiles loadFiles = cv.LoadAction(devId, + filenames[0], filenames[1],filenames[2]); + if (loadFiles.rc == 0) { + int[] sizes = new int[3]; + if (loadFiles.file1 != null) sizes[0] = loadFiles.file1.length; + if (loadFiles.file2 != null) sizes[1] = loadFiles.file2.length; + if (loadFiles.file3 != null) sizes[2] = loadFiles.file3.length; + appendDisplayText("Loaded File sizes: " + + " 1:" + sizes[0] + + " 2:" + sizes[1] + + " 3:" + sizes[2] + + "\n"); + km = cv.GenerateKM(loadFiles.file1, loadFiles.file2); + tm = cv.GenerateTM(loadFiles.file3); + } + + byte[] data = new byte[ccbVaultIc.CCBVAULTIC_INFO_LEN]; + int rc = cv.GetInfoText(devId, data); + appendDisplayText("GetInfoText rc=" + rc + "\n" + new String(data)); + };break; + } + } + else { + appendDisplayText("B. Using internal crypto.\n"); wolfProv.setDevId(WolfSSL.INVALID_DEVID); } ts[2] = System.currentTimeMillis(); - appendDisplayText("C. Setting up context and socket\n"); - - /* not setting up KeyStore or TrustStore, wolfJSSE will load - * CA certs from the Android system KeyStore by default. */ - SSLContext ctx = SSLContext.getInstance("TLS", wolfProv.getName()); - ctx.init(null, null, null); - - SSLSocketFactory sf = ctx.getSocketFactory(); - SSLSocket sock = (SSLSocket) sf.createSocket(host, port); - - if (limitCipherProtocol) { - /* Limit cipherSuites and protocol */ - String[] cipherSuites = new String[]{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}; - sock.setEnabledCipherSuites(cipherSuites); - String[] protocols = new String[]{"TLSv1.2"}; - sock.setEnabledProtocols(protocols); - } - ts[3] = System.currentTimeMillis(); - appendDisplayText("D. Starting Handshake\n"); - sock.startHandshake(); - - ts[4] = System.currentTimeMillis(); - appendDisplayText("E. Sending GET Request\n"); - String getCmd = "GET / HTTP/1.1\r\n" + - "Host: www.wolfssl.com\r\n" + - "Accept: */*\r\n\r\n"; - sock.getOutputStream().write(getCmd.getBytes()); - - ts[5] = System.currentTimeMillis(); - long sizeLimit = 10 * 1024; - appendDisplayText("F. Receiving at least " + sizeLimit + " bytes\n"); - byte[] data = new byte[4 * 1024]; - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - long totalRead = 0; - /* Read the first 10kB */ - while (totalRead < sizeLimit) { - int nRead = sock.getInputStream().read(data, 0, data.length); - if (nRead < 0) break; - buffer.write(data, 0, nRead); - totalRead = totalRead + nRead; + // Skip the connection if we are doing HW MANU + if((devId == WolfSSL.INVALID_DEVID)||((connectCount % 3) != 2)) { + appendDisplayText("C. Setting up context and socket\n"); + + SSLContext ctx = SSLContext.getInstance("TLS", wolfProv.getName()); + /* not setting up KeyStore or TrustStore, wolfJSSE will load + * CA certs from the Android system KeyStore by default. */ + ctx.init(km, tm, null); + + SSLSocketFactory sf = ctx.getSocketFactory(); + SSLSocket sock = (SSLSocket) sf.createSocket(host, port); + + if (limitCipherProtocol) { + /* Limit cipherSuites and protocol */ + String[] cipherSuites = new String[]{"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"}; + sock.setEnabledCipherSuites(cipherSuites); + String[] protocols = new String[]{"TLSv1.2"}; + sock.setEnabledProtocols(protocols); + } + + ts[3] = System.currentTimeMillis(); + appendDisplayText("D. Starting Handshake\n"); + sock.startHandshake(); + + ts[4] = System.currentTimeMillis(); + appendDisplayText("E. Sending GET Request\n"); + sock.getOutputStream().write(getCmd.getBytes()); + + ts[5] = System.currentTimeMillis(); + long sizeLimit = 10 * 1024; + appendDisplayText("F. Receiving at least " + sizeLimit + " bytes\n"); + byte[] data = new byte[4 * 1024]; + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + /* Read the first 10kB */ + while (totalRead < sizeLimit) { + int nRead = sock.getInputStream().read(data, 0, data.length); + if (nRead < 0) break; + buffer.write(data, 0, nRead); + totalRead = totalRead + nRead; + } + + ts[6] = System.currentTimeMillis(); + appendDisplayText("G. Closing socket\n"); + sock.close(); + + ts[7] = System.currentTimeMillis(); } - - ts[6] = System.currentTimeMillis(); - appendDisplayText("G. Closing socket\n"); - sock.close(); - - ts[7] = System.currentTimeMillis(); - if (((connectCount % 2) == 0) && (devId != WolfSSL.INVALID_DEVID)) { - appendDisplayText("H. Disabling hardware offload\n"); - wolfProv.setDevId(WolfSSL.INVALID_DEVID); - wolfProv.unRegisterDevId(devId); + if(devId != WolfSSL.INVALID_DEVID) { + switch(connectCount % 3) { + case 1: //SW + { + appendDisplayText("H. Software crypto still enabled\n"); + };break; + case 0: //HW -App + case 2: //HW - Manu + { + appendDisplayText("H. Disabling hardware offload\n"); + wolfProv.setDevId(WolfSSL.INVALID_DEVID); + wolfProv.unRegisterDevId(devId); + };break; + } } else { - appendDisplayText("H. Software crypto still enabled\n"); + appendDisplayText("H. Internal crypto still enabled\n"); } ts[8] = System.currentTimeMillis(); diff --git a/ccb_vaultic/Makefile b/ccb_vaultic/Makefile index c17b79680..0b53e0738 100644 --- a/ccb_vaultic/Makefile +++ b/ccb_vaultic/Makefile @@ -6,7 +6,7 @@ AR=${NDK_AR} LD=${NDK_LD} # Relative path to wolfSSL source -WOLFSSL_DIR?=../../wolfssl +WOLFSSL_DIR?=../../bill_wolfssl # Relative path to VaultIC dev kit source VAULTIC_DIR?=./VaultIC-TLS_420/vaultic_tls-4xx @@ -53,7 +53,7 @@ TEST_OBJS:=$(WOLFSSL_DIR)/wolfcrypt/test/test.o main-test.o BENCH_OBJS:=$(WOLFSSL_DIR)/wolfcrypt/benchmark/benchmark.o main-bench.o #Makefile rules -all: wolfcrypt-test wolfcrypt-benchmark +all: wolfcrypt-test wolfcrypt-benchmark vlt-load vlt-prov wolfcrypt-test: $(OBJS) $(TEST_OBJS) $(CC) -o $@ $^ $(LDFLAGS) @@ -61,7 +61,13 @@ wolfcrypt-test: $(OBJS) $(TEST_OBJS) wolfcrypt-benchmark: $(OBJS) $(BENCH_OBJS) $(CC) -o $@ $^ $(LDFLAGS) +vlt-load: $(OBJS) main-load.o + $(CC) -o $@ $^ $(LDFLAGS) + +vlt-prov: $(OBJS) main-prov.o + $(CC) -o $@ $^ $(LDFLAGS) + clean: - rm -f *.o *.d wolfcrypt-test wolfcrypt-benchmark + rm -f *.o *.d wolfcrypt-test wolfcrypt-benchmark vlt-load vlt-prov rm -f $(WOLFSSL_DIR)/wolfcrypt/benchmark/*.o rm -f $(WOLFSSL_DIR)/wolfcrypt/test/*.o diff --git a/ccb_vaultic/ccb_vaultic.c b/ccb_vaultic/ccb_vaultic.c index 74e51994f..e590b82d5 100644 --- a/ccb_vaultic/ccb_vaultic.c +++ b/ccb_vaultic/ccb_vaultic.c @@ -39,6 +39,7 @@ * CCBVAULTIC_NO_RSA: Do not handle RSA callback * CCBVAULTIC_NO_AES: Do not handle AES callback * + * * Expected wolfSSL/wolfCrypt defines from wolfcrypt/types.h or settings.h: * XMALLOC: malloc() equivalent * XREALLOC: realloc() equivalent @@ -67,6 +68,9 @@ /* Local include */ #include "ccb_vaultic.h" +/* Provide default config struct if needed */ +ccbVaultIc_Config gDefaultConfig = CCBVAULTIC_CONFIG_DEFAULT; + /* Debug defines */ #ifdef CCBVAULTIC_DEBUG_ALL #ifndef CCBVAULTIC_DEBUG @@ -84,45 +88,66 @@ #endif - /* wolfcrypt includes */ -#include "wolfssl/wolfcrypt/types.h" /* types and X-defines */ +#include "wolfssl/wolfcrypt/types.h" /* types and X-defines */ -#ifndef CCBVAULTIC_NO_SHA -#include "wolfssl/wolfcrypt/hash.h" /* For HASH_FLAGS and types */ -#endif +#include "wolfssl/wolfcrypt/hmac.h" /* For HMACSHA256 */ +/* Always need hash and hmac for kdf auth */ +#include "wolfssl/wolfcrypt/hash.h" /* For HASH_FLAGS and types */ #ifndef CCBVAULTIC_NO_RSA -#include "wolfssl/wolfcrypt/rsa.h" /* For RSA_MAX_SIZE and types */ +#include "wolfssl/wolfcrypt/rsa.h" /* For RSA_MAX_SIZE and types */ #endif #ifndef CCBVAULTIC_NO_AES -#include "wolfssl/wolfcrypt/aes.h" /* For AES_BLOCK_SIZE and types */ +#include "wolfssl/wolfcrypt/aes.h" /* For AES_BLOCK_SIZE and types */ #endif -#ifdef CCBVAULTIC_DEBUG_TIMING - #ifndef XNOW - #include - #include - #define XNOW(...) _now(__VA_ARGS__) - - static uint64_t _now(void) - { - struct timespec t; - if (clock_gettime(CLOCK_MONOTONIC, &t) < 0) - /* Return 0 on error */ - return 0; - return (uint64_t)t.tv_sec * 1000000000ull + t.tv_nsec; - } - #endif +#if defined(CCBVAULTIC_DEBUG_TIMING) && !defined(XNOW) +#include +#include +#define XNOW(...) _Now(__VA_ARGS__) + +static uint64_t _Now(void) +{ + struct timespec t; + if (clock_gettime(CLOCK_MONOTONIC, &t) < 0) + /* Return 0 on error */ + return 0; + return (uint64_t)t.tv_sec * 1000000000ull + t.tv_nsec; +} +#endif + +#ifdef CCBVAULTIC_DEBUG +/* Helper to provide simple _HexDump */ +static void _HexDump(const char* p, size_t data_len) +{ + XPRINTF(" HD:%p for %lu bytes\n",p, data_len); + if ( (p == NULL) || (data_len == 0)) + return; + size_t off = 0; + for (off = 0; off < data_len; off++) + { + if ((off % 16) == 0) + XPRINTF(" "); + XPRINTF("%02X ", p[off]); + if ((off % 16) == 15) + XPRINTF("\n"); + } + if ( (off%16) != 15) + XPRINTF("\n"); +} #endif + /* WiseKey VaultIC includes */ #include "vaultic_tls.h" #include "vaultic_config.h" #include "vaultic_common.h" #include "vaultic_api.h" #include "vaultic_structs.h" +#include "auth/vaultic_identity_authentication.h" +#include "vaultic_file_system.h" /* Key/Group ID's to support temporary wolfSSL usage */ #define CCBVAULTIC_WOLFSSL_GRPID 0xBB @@ -135,29 +160,8 @@ #define VAULTIC_PKV_ASSURED VLT_PKV_ASSURED_EXPLICIT_VALIDATION -#ifdef CCBVAULTIC_DEBUG -/* Helper to provide simple hexdump */ -static void hexdump(const unsigned char* p, size_t len) -{ - XPRINTF(" HD:%p for %lu bytes\n",p, len); - if ( (p == NULL) || (len == 0)) - return; - size_t off = 0; - for (off = 0; off < len; off++) - { - if ((off % 16) == 0) - XPRINTF(" "); - XPRINTF("%02X ", p[off]); - if ((off % 16) == 15) - XPRINTF("\n"); - } - if ( (off%16) != 15) - XPRINTF("\n"); -} -#endif - /* Helper to translate vlt return codes to wolfSSL code */ -static int translateError(int vlt_rc) +static int _TranslateError(int vlt_rc) { /* vlt return codes are defined in src/common/vaultic_err.h */ switch (vlt_rc) { @@ -165,44 +169,425 @@ static int translateError(int vlt_rc) case VLT_OK: return 0; default: - /* Default to point to hardware */ - return WC_HW_E; + /* Default to point to IO */ + return IO_FAILED_E; + } +} + +static int _GetInfo(ccbVaultIc_Context *c, VLT_TARGET_INFO *out_chipInfo) +{ + if ((c == NULL) || (out_chipInfo == NULL)) { + return BAD_FUNC_ARG; + } + XMEMSET(out_chipInfo, 0, sizeof(*out_chipInfo)); + + /* Get current chip info */ + c->vlt_rc = VltGetInfo(out_chipInfo); +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("_GetInfo: vlt_rc:%04X serial:%p firmware:%.*s, \n" \ + "mode:%d, state:%02X, selftests:%d, space:%d\n", + c->vlt_rc, out_chipInfo->au8Serial, + (int)sizeof(out_chipInfo->au8Firmware), out_chipInfo->au8Firmware, + out_chipInfo->enMode, out_chipInfo->enState, out_chipInfo->enSelfTests, + (int)out_chipInfo->u32Space); + _HexDump((const char*)out_chipInfo->au8Serial, sizeof(out_chipInfo->au8Serial)); +#endif + return _TranslateError(c->vlt_rc); +} + +static int _GetInfoText(ccbVaultIc_Context* c, int text_len, char* text, + int *out_len) +{ + VLT_TARGET_INFO chipInfo; + int rc = _GetInfo(c, &chipInfo); + if ((rc == 0) && (text != NULL) && (text_len > 0)) { + int len = snprintf(text, text_len, + "VERSION:%.*s\n" + "SERIAL:%02X%02X%02X%02X%02X%02X%02X%02X\n" + "STATE:%02X\n" + "MODE:%02X\n" + "ROLE:%02X\n" + "SELFTEST:%02X\n" + "SPACE:%d\n", + (int)sizeof(chipInfo.au8Firmware), + (const char*)chipInfo.au8Firmware, + chipInfo.au8Serial[0], + chipInfo.au8Serial[1], + chipInfo.au8Serial[2], + chipInfo.au8Serial[3], + chipInfo.au8Serial[4], + chipInfo.au8Serial[5], + chipInfo.au8Serial[6], + chipInfo.au8Serial[7], + chipInfo.enState, + chipInfo.enMode, + chipInfo.enRole, + chipInfo.enSelfTests, + (int)chipInfo.u32Space); + if (out_len != NULL) { + *out_len = len; + } + } + return rc; +} + +static VLT_USER_ID _AuthId2VltUserId(int id) +{ + switch(id) { + case 0: return VLT_USER0; + case 1: return VLT_USER1; + case 2: return VLT_USER2; + case 3: return VLT_USER3; + case 4: return VLT_USER4; + case 5: return VLT_USER5; + case 6: return VLT_USER6; + case 7: + default: break; + } + return VLT_USER7; +} +static VLT_ROLE_ID _AuthRole2VltRoleId(int role) +{ + switch(role) { + case CCBVAULTIC_AUTH_ROLE_NONE: return VLT_EVERYONE; + case CCBVAULTIC_AUTH_ROLE_APPROVED: return VLT_APPROVED_USER; + case CCBVAULTIC_AUTH_ROLE_UNAPPROVED: return VLT_NON_APPROVED_USER; + case CCBVAULTIC_AUTH_ROLE_MANUFACTURER: return VLT_MANUFACTURER; + default: + break; } + return VLT_EVERYONE; } -static void clearContext(ccbVaultIc_Context *c) +/* Perform HMAC SHA256 on input data to generate 2 keys up to 32 bytes total */ +static int _PerformKdf(int key_len, const char* key, + int in1_len, const char* in1, + int in2_len, const char* in2, + int in3_len, const char* in3, + int out1_len, char* out1, + int out2_len, char* out2) { + Hmac kdf; + int rc; + if ( (key_len == 0) || (key == NULL) || /* Key is required */ + ((in1_len <= 0) && (in1 == NULL)) || + ((in2_len <= 0) && (in2 == NULL)) || + ((in3_len <= 0) && (in3 == NULL)) || + ((out1_len <= 0) && (out1 == NULL)) || + ((out2_len <= 0) && (out2 == NULL)) ){ + return BAD_FUNC_ARG; + } + + rc = wc_HmacInit(&kdf, NULL, INVALID_DEVID); + if (rc == 0) { + int out_count=0; + byte digest[WC_SHA256_DIGEST_SIZE]; + XMEMSET(digest, 0, sizeof(digest)); + + rc = wc_HmacSetKey(&kdf, WC_SHA256, (const byte*)key, key_len); + if (rc == 0) { + rc = wc_HmacUpdate(&kdf, (const byte*)in1, in1_len); + } + if ((rc == 0) && (in2_len > 0) && (in2 != NULL)) { + rc = wc_HmacUpdate(&kdf, (const byte*)in2, in2_len); + } + if ((rc == 0) && (in3_len > 0) && (in3 != NULL)) { + rc = wc_HmacUpdate(&kdf, (const byte*)in3, in3_len); + } + if (rc == 0) { + rc = wc_HmacFinal(&kdf, digest); + if ((rc == 0) && (out1_len > 0)) { + int this_len = sizeof(digest) - out_count; + if (this_len > out1_len) this_len = out1_len; + XMEMCPY(out1, &digest[out_count], this_len); + XMEMSET(out1 + this_len, 0, out1_len - this_len); + out_count += this_len; + } + if ((rc == 0) && (out2_len > 0)) { + int this_len = sizeof(digest) - out_count; + if (this_len > out2_len) this_len = out2_len; + XMEMCPY(out2, &digest[out_count], this_len); + XMEMSET(out2 + this_len, 0, out2_len - this_len); + out_count += this_len; + } + } + wc_HmacFree(&kdf); + } +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("_PerformKdf: rc:%d key_len:%d key:%p, \n" + "in1_len:%d in1:%p, in2_len:%d in2:%p,in3_len:%d in3:%p \n" + "out1_len:%d out1:%p, out2_len:%d out2:%p,\n", + rc, key_len, key, + in1_len, in1, in2_len, in2, in3_len, in3, + out1_len, out1, out2_len, out2); + _HexDump(key, key_len); + _HexDump(in1, in1_len); + _HexDump(in2, in2_len); + _HexDump(in3, in3_len); + _HexDump(out1, out1_len); + _HexDump(out2, out2_len); +#endif + + return rc; +} + +static int _AuthByPin( ccbVaultIc_Context *c, int id, int role, + int pin_len, const char* pin) +{ + if ((pin_len > CCBVAULTIC_AUTH_PIN_LEN_MAX) || + (pin_len < CCBVAULTIC_AUTH_PIN_LEN_MIN)) { + return BAD_FUNC_ARG; + } +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("_AuthByPin: c:%p id:%d role:%d, pin_len:%d pin:%p\n", + c, id, role, pin_len, pin); + _HexDump(pin, pin_len); +#endif + /* Auth using password. */ + c->vlt_rc= VltSubmitPassword( + _AuthId2VltUserId(id), + _AuthRole2VltRoleId(role), + (VLT_U8) pin_len, + (VLT_PU8) pin); + return _TranslateError(c->vlt_rc); +} + +static int _AuthByScp03( ccbVaultIc_Context *c, int id, int role, + int mac_len, char* mac, + int enc_len, char* enc) +{ + KEY_BLOB macKey; + KEY_BLOB encKey; + KEY_BLOB_ARRAY keys; + +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("_AuthByScp03: c:%p id:%d, role:%d, " + " mac_len:%d mac:%p, enc_len:%d enc:%p\n", + c, id, role, + mac_len, mac, enc_len, enc); + _HexDump(mac, mac_len); + _HexDump(enc, enc_len); +#endif + XMEMSET(&macKey, 0, sizeof(macKey)); + XMEMSET(&encKey, 0, sizeof(encKey)); + XMEMSET(&keys, 0, sizeof(keys)); + + macKey.keyType = VLT_KEY_AES_128; + macKey.keySize = (VLT_U16) mac_len; + macKey.keyValue = (VLT_PU8) mac; + + encKey.keyType = VLT_KEY_AES_128; + encKey.keySize = (VLT_U16) enc_len; + encKey.keyValue = (VLT_PU8) enc; + + keys.u8ArraySize = 2; + keys.pKeys[0] = &macKey; + keys.pKeys[1] = &encKey; + + c->vlt_rc=VltAuthInit( + VLT_AUTH_SCP03, + _AuthId2VltUserId(id), + _AuthRole2VltRoleId(role), + VLT_CMAC_CENC_RMAC_RENC, + keys); + return _TranslateError(c->vlt_rc); +} + +static int _AuthByKdf( ccbVaultIc_Context *c, int id, int role, + int key_len, const char* key, + int label_len, const char* label) +{ + char mac_data[CCBVAULTIC_AUTH_MAC_LEN]; + char enc_data[CCBVAULTIC_AUTH_ENC_LEN]; + +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("_AuthByKdf: c:%p id:%d role:%d, " + "key_len:%d key:%p, label_len:%d label:%p\n", + c, id, role, + key_len, key, label_len, label); + _HexDump(key, key_len); + _HexDump(label, label_len); +#endif + + int rc = _PerformKdf( key_len, key, + label_len, label, + CCBVAULTIC_SERIAL_LEN, c->vlt_serial, + CCBVAULTIC_VERSION_LEN, c->vlt_version, + sizeof(mac_data), mac_data, + sizeof(enc_data), enc_data); + if (rc == 0) { + rc = _AuthByScp03( c, id, role, + sizeof(mac_data), mac_data, + sizeof(enc_data), enc_data); + } + return rc; +} + +/* Helper to perform auth as the provided user */ +static int _InitAuth(ccbVaultIc_Context *c, const ccbVaultIc_Auth *a) +{ + int rc = 0; + if ((c == NULL) || (c->initialized != 0) || (a == NULL)) { + return BAD_FUNC_ARG; + } + +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("_InitAuth: c:%p a:%p kind:%d\n", + c, a, a->kind); +#endif + + switch(a->kind) { + case CCBVAULTIC_AUTH_KIND_NONE: + { + /* Ok. Unexpected, but not an error */ + rc = 0; + }; break; + + case CCBVAULTIC_AUTH_KIND_PIN: + { + rc = _AuthByPin(c, a->id, a->role, + a->auth.pin.pin_len,a->auth.pin.pin); + };break; + + case CCBVAULTIC_AUTH_KIND_SCP03: + { + char mac_data[CCBVAULTIC_AUTH_MAC_LEN]; + char enc_data[CCBVAULTIC_AUTH_ENC_LEN]; + + if ( (a->auth.scp03.mac_len < sizeof(mac_data)) || + (a->auth.scp03.enc_len < sizeof(enc_data))) { + rc = BAD_FUNC_ARG; + break; + } + + /* Copy to temp buffer to support const auth */ + XMEMCPY(mac_data, a->auth.scp03.mac, sizeof(mac_data)); + XMEMCPY(enc_data, a->auth.scp03.enc, sizeof(enc_data)); + rc = _AuthByScp03( c, a->id, a->role, + sizeof(mac_data), mac_data, + sizeof(enc_data), enc_data); + };break; + + case CCBVAULTIC_AUTH_KIND_KDF: + { + rc = _AuthByKdf( c, a->id, a->role, + a->auth.kdf.key_len, a->auth.kdf.key, + a->auth.kdf.label_len, a->auth.kdf.label); + };break; + + default: + rc = BAD_FUNC_ARG; + } + return rc; +} + +/* Helper to check for NULL and uninitialized contexts */ +static int _CheckInitializedContext(ccbVaultIc_Context *c) +{ + if ((c == NULL) || (c->initialized == 0)) { + return BAD_FUNC_ARG; + } + return 0; +} + +static void _ClearContext(ccbVaultIc_Context *c) +{ + const ccbVaultIc_Config* saveConfig = c->config; XMEMSET(c, 0, sizeof(*c)); + c->config=saveConfig; c->m = NULL; c->aescbc_key = NULL; } +int ccbVaultIc_GetDefaultConfig(ccbVaultIc_Config* *out_c) +{ + if (out_c == NULL) { + return BAD_FUNC_ARG; + } + *out_c = &gDefaultConfig; + return 0; +} + int ccbVaultIc_Init(ccbVaultIc_Context *c) { int rc = 0; if (c == NULL) { - rc = BAD_FUNC_ARG; + return BAD_FUNC_ARG; } /* Already Initialized? */ - if ((rc == 0) && (c->initialized >0)) { + if (c->initialized > 0) { /* Increment use count */ c->initialized++; return 0; } + _ClearContext(c); + + /* Open the hardware and authenticate */ +#if 0 + c->vlt_rc = vlt_tls_init(); + rc = _TranslateError(c->vlt_rc); +#else + const ccbVaultIc_Config* config = &gDefaultConfig; + VLT_INIT_COMMS_PARAMS params; + + + /* Override config */ + if (c->config != NULL) { + config = c->config; + } + + /* Set timeout, checksum, and interface type */ + XMEMSET(¶ms, 0, sizeof(params)); + params.VltBlockProtocolParams.u16msSelfTestDelay = config->startup_delay_ms; + params.VltBlockProtocolParams.u32msTimeout = config->timeout_ms; + params.VltBlockProtocolParams.enCheckSumMode = BLK_PTCL_CHECKSUM_SUM8; + params.enCommsProtocol = VLT_SPI_COMMS; + params.VltSpiParams.u16BitRate = config->spi_rate_khz; + + /* Initialize the API and establish comms*/ + c->vlt_rc = VltApiInit(¶ms); + rc = _TranslateError(c->vlt_rc); if (rc == 0) { - clearContext(c); - /* Open the hardware and authenticate */ - c->vlt_rc = vlt_tls_init(); - rc = translateError(c->vlt_rc); + VLT_TARGET_INFO chipInfo; + + /* Cancel any active authentication, Ignore errors here */ + VltAuthClose(); + + /* Get current chip info */ + rc = _GetInfo(c, &chipInfo); + if (rc == 0) { +#ifdef CCBVAULTIC_DEBUG + XPRINTF("ccbVaultIc_Info: serial:%p firmware:%.*s, \n" \ + "mode:%d, state:%d, selftests:%d, space:%d\n", + chipInfo.au8Serial, + (int)sizeof(chipInfo.au8Firmware), chipInfo.au8Firmware, + chipInfo.enMode, chipInfo.enState, chipInfo.enSelfTests, + (int)chipInfo.u32Space); + _HexDump((const char*)chipInfo.au8Serial, sizeof(chipInfo.au8Serial)); +#endif + + /* Save this data to the context */ + XMEMCPY(c->vlt_serial, chipInfo.au8Serial, sizeof(chipInfo.au8Serial)); + XMEMCPY(c->vlt_version, chipInfo.au8Firmware, sizeof(chipInfo.au8Firmware)); + + /* Ensure chip is not TERMINATED and no one is auth'ed */ + if ( (chipInfo.enState == VLT_STATE_TERMINATED) || + (chipInfo.enRole != VLT_EVERYONE)){ + /* Nothing to do. Return hardware error */ + rc = WC_HW_E; + } + if (rc == 0) { + rc = _InitAuth(c, &config->auth); + } + } } +#endif + if (rc == 0) { c->initialized = 1; } - else { - /* Override with an init error */ - rc = WC_INIT_E; - } + #ifdef CCBVAULTIC_DEBUG XPRINTF("ccbVaultIc_Init: c:%p c->initialized:%d rc:%d vlt_rc:%d\n", c, @@ -236,13 +621,431 @@ void ccbVaultIc_Cleanup(ccbVaultIc_Context *c) if (c->aescbc_key != NULL) XFREE(c->aescbc_key, NULL, NULL); - clearContext(c); + _ClearContext(c); /* Set the return value in the struct */ /* Close the hardware */ c->vlt_rc = vlt_tls_close(); } +int ccbVaultIc_SelfTest( ccbVaultIc_Context *c) +{ + int rc = _CheckInitializedContext(c); + if (rc == 0) { + //XXX SKIP FOR NOW. Failure will set TERMINATED + //c->vlt_rc = VltSelfTest(); + c->vlt_rc = VLT_OK; + rc = _TranslateError(c->vlt_rc); + } + return rc; +} +/* Helper. Missing XSTRNLEN */ +static int ccbVaultIc_Strnlen(const char *s, int n) +{ + int len = 0; + while( (len < n) && (s[len] != 0)) { + len++; + } + return len; +} + +static int _CheckFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f, + int userId, int adminId) +{ + int rc = _CheckInitializedContext(c); + if (rc == 0) { + if ( (f == NULL) || + (f->name_len < CCBVAULTIC_FILE_NAME_LEN_MIN) || + (f->name_len > CCBVAULTIC_FILE_NAME_LEN_MAX) || + (f->data_len > CCBVAULTIC_FILE_DATA_LEN_MAX) || + (userId < CCBVAULTIC_AUTH_ID_MIN) || + (userId > CCBVAULTIC_AUTH_ID_MAX) || + (adminId < CCBVAULTIC_AUTH_ID_MIN) || + (adminId > CCBVAULTIC_AUTH_ID_MAX)) { + rc = BAD_FUNC_ARG; + } + } + return rc; +} + +static int _OpenFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f, + int *out_dataLen) +{ + int rc = _CheckFile(c, f, + CCBVAULTIC_AUTH_ID_MIN, CCBVAULTIC_AUTH_ID_MIN /* Dummy Ids */ + ); + if (rc == 0) { + VLT_FS_ENTRY_PARAMS structFileEntry; + XMEMSET(&structFileEntry, 0, sizeof(structFileEntry)); + + c->vlt_rc = VltFsOpenFile( + (VLT_U16)f->name_len, + (VLT_U8*)f->name, + (VLT_BOOL)FALSE, /* No transaction */ + &structFileEntry); + rc = _TranslateError(c->vlt_rc); + +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("ccbVaultIc_OpenFile rc:%d (%x) c:%p f:%p name_len:%d name:%.*s, data_len:%d data:%p\n", + rc, c->vlt_rc, c, f, f->name_len, (int)f->name_len, f->name, f->data_len, f->data); +#endif + /* Update output on success */ + if ((rc == 0) && (out_dataLen != NULL)) { + *out_dataLen = structFileEntry.u32FileSize; + } + } + return rc; +} + +static void _SetVltUserAccessBit(VLT_USER_ACCESS* u, int userId) +{ + if (u == NULL) { + return; + } + switch(userId) { + case 0: u->user0 = 1; return; + case 1: u->user1 = 1; return; + case 2: u->user2 = 1; return; + case 3: u->user3 = 1; return; + case 4: u->user4 = 1; return; + case 5: u->user5 = 1; return; + case 6: u->user6 = 1; return; + case 7: u->user7 = 1; return; + default: break; + } +} + +int ccbVaultIc_CreateUserFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f, + int userId, int adminId) +{ + int rc = _CheckFile(c, f, userId, adminId); + if (rc == 0) { + VLT_USER_ACCESS priv; + VLT_FS_ENTRY_PARAMS entryParams; + + XMEMSET(&priv, 0, sizeof(priv)); + XMEMSET(&entryParams, 0, sizeof(entryParams)); + + /* All privileges for the user and the admin */ + _SetVltUserAccessBit(&priv, userId); + _SetVltUserAccessBit(&priv, adminId); + entryParams.filePriv.readPrivilege = priv; + entryParams.filePriv.writePrivilege = priv; + entryParams.filePriv.deletePrivilege = priv; + entryParams.filePriv.executePrivilege = priv; + entryParams.attribs.readOnly = 0; /* Read/Write */ + entryParams.attribs.system = 0; /* Non-system */ + entryParams.attribs.hidden = 0; /* Visible */ + entryParams.u32FileSize = 0; /* Empty */ + entryParams.u8EntryType = VLT_FILE_ENTRY; + + c->vlt_rc = VltFsCreate( + (VLT_U16)f->name_len+1, + (VLT_PU8)f->name, + &entryParams, + (VLT_USER_ID) userId); /* Owner */ + rc = _TranslateError(c->vlt_rc); +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("ccbVaultIc_CreateUserFile rc:%d (%x) c:%p f:%p name_len:%d name:%.*s\n", + rc, c->vlt_rc, c, f, f->name_len, (int)f->name_len, f->name); +#endif + } + return rc; +} + +int ccbVaultIc_DeleteFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f) +{ + + int rc = _CheckFile(c, f, + CCBVAULTIC_AUTH_ID_MIN, CCBVAULTIC_AUTH_ID_MIN /* Dummy Ids */ + ); + if (rc == 0) { + c->vlt_rc = VltFsDelete( + (VLT_U16)f->name_len, + (VLT_U8*)f->name, + (VLT_BOOL)FALSE); /* Not recursive */ + rc = _TranslateError(c->vlt_rc); +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("ccbVaultIc_DeleteFile rc:%d (%x) c:%p f:%p name_len:%d name:%.*s\n", + rc, c->vlt_rc, c, f, f->name_len, (int)f->name_len, f->name); +#endif + } + return rc; +} + +int ccbVaultIc_WriteFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f) +{ + int rc = _OpenFile(c, f, NULL); + if (rc == 0) { + c->vlt_rc = VltFsWriteFile( + (VLT_U32)VLT_SEEK_FROM_START, + (VLT_U8*)f->data, + (VLT_U32)f->data_len, + (VLT_BOOL)TRUE); /* Reclaim space */ + rc = _TranslateError(c->vlt_rc); +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("ccbVaultIc_WriteFile rc:%d (%x) c:%p f:%p name_len:%d name:%.*s, data_len:%d data:%p\n", + rc, c->vlt_rc, c, f, f->name_len, (int)f->name_len, f->name, f->data_len, f->data); + _HexDump(f->data, f->data_len); +#endif + + /* Close and ignore error here */ + VltFsCloseFile(); + } + return rc; +} + +int ccbVaultIc_ReadFile( ccbVaultIc_Context *c, + ccbVaultIc_File *f) +{ + int fileLen = 0; + int maxLen = f->data_len; + int rc = _OpenFile(c, f, &fileLen); + if (rc == 0) { + VLT_U32 readLen = fileLen; + if (readLen > maxLen) { + readLen = maxLen; + } + + /* Reset file struct data */ + XMEMSET(f->data, 0, maxLen); + + c->vlt_rc = VltFsReadFile( + (VLT_U32)VLT_SEEK_FROM_START, + (VLT_U8*) f->data, + &readLen); + rc = _TranslateError(c->vlt_rc); + + if (rc == 0) { + /* Success. Update file struct */ + f->data_len = readLen; + } +#ifdef CCBVAULTIC_DEBUG_ALL + XPRINTF("ccbVaultIc_ReadFile rc:%d (%x) c:%p f:%p name_len:%d name:%.*s, data_len:%d data:%p\n", + rc, c->vlt_rc, c, f, f->name_len, (int)f->name_len, f->name, f->data_len, f->data); + _HexDump(f->data, f->data_len); +#endif + + /* Close and ignore error here */ + VltFsCloseFile(); + } + return rc; +} + +static int _DeleteUser(ccbVaultIc_Context *c, const ccbVaultIc_Auth *a) +{ + int rc = _CheckInitializedContext(c); + if (rc == 0) { + if (a == NULL) { + rc = BAD_FUNC_ARG; + } + if(rc == 0) { + VLT_MANAGE_AUTH_DATA authData; + XMEMSET(&authData, 0, sizeof(authData)); + authData.enOperationID = VLT_DELETE_USER; + authData.enUserID = _AuthId2VltUserId(a->id); + + c->vlt_rc = VltManageAuthenticationData(&authData); + rc = _TranslateError(c->vlt_rc); + } + } + return rc; +} +static int _CreateUser_SCP03(ccbVaultIc_Context *c, int id, int role, + int mac_len, char* mac, + int enc_len, char* enc) +{ + int rc = 0; + VLT_MANAGE_AUTH_DATA authData; + XMEMSET(&authData, 0, sizeof(authData)); + + authData.enOperationID = VLT_CREATE_USER; + authData.enUserID = _AuthId2VltUserId(id); + authData.u8TryCount = 5; /* From VLT example */ + authData.enSecurityOption = VLT_NO_DELETE_ON_LOCK; + authData.enRoleID = _AuthRole2VltRoleId(role); + authData.enMethod = VLT_AUTH_SCP03; + authData.enChannelLevel = VLT_CMAC_CENC; + authData.data.secret.u8NumberOfKeys = 2; + authData.data.secret.aKeys[0].enKeyID = VLT_KEY_AES_128; + authData.data.secret.aKeys[0].u8Mask = 0xBE; + authData.data.secret.aKeys[0].u16KeyLength = mac_len; + authData.data.secret.aKeys[0].pu8Key = (VLT_PU8) mac; + authData.data.secret.aKeys[1].enKeyID = VLT_KEY_AES_128; + authData.data.secret.aKeys[1].u8Mask = 0xEF; + authData.data.secret.aKeys[1].u16KeyLength = enc_len; + authData.data.secret.aKeys[1].pu8Key = (VLT_PU8) enc; + + c->vlt_rc = VltManageAuthenticationData(&authData); + rc = _TranslateError(c->vlt_rc); + return rc; +} +static int _CreateUser(ccbVaultIc_Context *c,const ccbVaultIc_Auth *a) +{ + int rc = _CheckInitializedContext(c); + if (rc == 0) { + if (a == NULL) { + rc = BAD_FUNC_ARG; + } + if(rc == 0) { + char mac[CCBVAULTIC_AUTH_MAC_LEN]; + char enc[CCBVAULTIC_AUTH_ENC_LEN]; + + XMEMSET (mac, 0, sizeof(mac)); + XMEMSET (enc, 0, sizeof(enc)); + switch (a->kind) { + case CCBVAULTIC_AUTH_KIND_SCP03: + { + XMEMCPY(mac, a->auth.scp03.mac, a->auth.scp03.mac_len); + XMEMCPY(enc, a->auth.scp03.enc, a->auth.scp03.enc_len); + rc = _CreateUser_SCP03(c, a->id, a->role, + a->auth.scp03.mac_len, mac, + a->auth.scp03.enc_len, enc); + };break; + case CCBVAULTIC_AUTH_KIND_KDF: + { + int rc = _PerformKdf( a->auth.kdf.key_len, a->auth.kdf.key, + a->auth.kdf.label_len, a->auth.kdf.label, + CCBVAULTIC_SERIAL_LEN, c->vlt_serial, + CCBVAULTIC_VERSION_LEN, c->vlt_version, + sizeof(mac), mac, + sizeof(enc), enc); + if (rc == 0) { + rc = _CreateUser_SCP03( c, a->id, a->role, + sizeof(mac), mac, + sizeof(enc), enc); + } + };break; + case CCBVAULTIC_AUTH_KIND_NONE: + case CCBVAULTIC_AUTH_KIND_PIN: + default: + rc = BAD_FUNC_ARG; + break; + } + } + } + return rc; +} + +static int _SetState(ccbVaultIc_Context *c, VLT_STATE state) +{ + int rc = _CheckInitializedContext(c); + if (rc == 0) { + VLT_TARGET_INFO chipInfo; + rc = _GetInfo(c, &chipInfo); + if (rc == 0) { + if (chipInfo.enState != state) { + c->vlt_rc = VltSetStatus(state); + rc = _TranslateError(c->vlt_rc); + } + } + } + return rc; +} +static int _SetCreationState(ccbVaultIc_Context *c) +{ + return _SetState(c, VLT_STATE_CREATION); +} +static int _SetActivatedState(ccbVaultIc_Context *c) +{ + return _SetState(c, VLT_STATE_ACTIVATED); +} + +/* Perform the load action as the currently authed user */ +int ccbVaultIc_LoadAction( ccbVaultIc_Context *c, + ccbVaultIc_Load *l) +{ + int rc = _CheckInitializedContext(c); + if (rc == 0) { + if (l == NULL) { + rc = BAD_FUNC_ARG; + } + /* Read file data into the load structure */ + if (rc == 0) { + int counter = 0; + for(counter = 0; counter < l->file_count; counter++) { + /* Ok to skip empty files */ + if( (l->file[counter].name != NULL) && + (l->file[counter].name_len > 0) && + (l->file[counter].data != NULL) && + (l->file[counter].data_len > 0)) { + rc = ccbVaultIc_ReadFile(c, &l->file[counter]); + if (rc != 0) break; + } + } + } + } + return rc; +} + +/* Perform the provision action as the currently authed user */ +int ccbVaultIc_ProvisionAction( ccbVaultIc_Context *c, + const ccbVaultIc_Provision *p) +{ + int rc = _CheckInitializedContext(c); + if (rc == 0) { + if (p == NULL) { + rc = BAD_FUNC_ARG; + } + + if (rc == 0) { + /* Setting creation mode should delete all users and their files */ + rc = _SetCreationState(c); + } + + if (rc == 0) { + /* Update self test configuration */ + // rc = ccbVaultIc_SetSelfTest(c, p->self_test); + } + + /* Add User */ + if (rc == 0) { + /* Create the requested user */ + _DeleteUser(c, &p->create); + rc = _CreateUser(c, &p->create); + } + + /* Create and write file data from the provision structure */ + if (rc == 0) { + int counter = 0; + int userId = p->create.id; + int adminId = 0; + const ccbVaultIc_Config *config = c->config; + if(config == NULL) { + ccbVaultIc_GetDefaultConfig(&config); + } + adminId = config->auth.id; + for(counter = 0; counter < p->file_count; counter++) { + if( (p->file[counter].name != NULL) && + (p->file[counter].name_len > 0)) { + /* Delete any existing file. Ignore errors */ + ccbVaultIc_DeleteFile(c, &p->file[counter]); + + /* Create the file */ + rc = ccbVaultIc_CreateUserFile(c, &p->file[counter], + userId, adminId); + if (rc == 0) { + /* Write the file */ + rc = ccbVaultIc_WriteFile(c, &p->file[counter]); + } + if (rc != 0) break; + } + } + } + + if (rc == 0) { + /* Set Activated State */ + rc = _SetActivatedState(c); + } + } + return rc; +} + #ifdef WOLF_CRYPTO_CB /* Forward declarations */ @@ -401,9 +1204,53 @@ static int HandleCmdCallback(int devId, wc_CryptoInfo* info, rc = 0; }; break; + case CCBVAULTIC_CMD_INFO: + { + /* Issue an info command and convert the results to a text string */ + ccbVaultIc_Info* i = info->cmd.ctx; + + char* text = NULL; + int text_len = 0; + + if(i != NULL) { + text = i->text; + text_len = i->text_len; + } + + rc = _GetInfoText(c, text_len, text, &text_len); + if(i != NULL) { + i->text_len = text_len; + } + }; break; + + case CCBVAULTIC_CMD_LOADACTION: + { + if(_CheckInitializedContext(c) != 0) + break; + rc = ccbVaultIc_LoadAction(c, info->cmd.ctx); + }; break; + + case CCBVAULTIC_CMD_PROVISIONACTION: + { + if(_CheckInitializedContext(c) != 0) + break; + rc = ccbVaultIc_ProvisionAction(c, info->cmd.ctx); + }; break; + + case CCBVAULTIC_CMD_SELFTEST: + { + if(_CheckInitializedContext(c) != 0) + break; + rc = ccbVaultIc_SelfTest(c); + }; break; + default: break; } +#if defined(CCBVAULTIC_DEBUG_ALL) + XPRINTF("HandleCmdCallback %d: c:%p rc:%d\n", info->cmd.type, c, rc); +#endif + return rc; } #endif @@ -460,9 +1307,9 @@ static int HandlePkCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" RSA Flatten Pub Key:%d, eSz:%u nSz:%u\n", rc, eSz, nSz); - hexdump(e,sizeof(e)); - hexdump(e_pad,sizeof(e_pad)); - hexdump(n,sizeof(n)); + _HexDump((const char*)e,sizeof(e)); + _HexDump((const char*)e_pad,sizeof(e_pad)); + _HexDump((const char*)n,sizeof(n)); #endif /* Set tmpRsaKey privileges */ keyPrivileges.u8Read = VAULTIC_KP_ALL; @@ -501,7 +1348,7 @@ static int HandlePkCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VLT PutKey:%x\n", c->vlt_rc); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; @@ -517,7 +1364,7 @@ static int HandlePkCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VLT InitAlgo:%x\n", c->vlt_rc); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; @@ -538,7 +1385,7 @@ static int HandlePkCallback(int devId, wc_CryptoInfo* info, XPRINTF(" VLT Encrypt:%x inSz:%u outSz:%lu\n", c->vlt_rc, info->pk.rsa.inLen, out_len); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; @@ -731,7 +1578,7 @@ static int HandleHashCallback(int devId, wc_CryptoInfo* info, (info->hash.inSz > 0)) { /* Buffer data */ if (c->m == NULL) { - c->m = XMALLOC(info->hash.inSz, NULL, NULL); + c->m = (unsigned char*)XMALLOC(info->hash.inSz, NULL, NULL); if (c->m == NULL) { /* Failure to allocate. Must return error */ #if defined(CCBVAULTIC_DEBUG) @@ -795,7 +1642,7 @@ static int HandleHashCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VltInit SHA256:%x\n", c->vlt_rc); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; @@ -811,7 +1658,7 @@ static int HandleHashCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VltUpdate SHA256:%x\n", c->vlt_rc); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; @@ -822,7 +1669,7 @@ static int HandleHashCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VltFinal SHA256:%x\n", c->vlt_rc); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; } @@ -835,9 +1682,9 @@ static int HandleHashCallback(int devId, wc_CryptoInfo* info, info->hash.digest); #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VltCompute SHA256:%x\n", c->vlt_rc); - hexdump(info->hash.digest, WC_SHA256_DIGEST_SIZE); + _HexDump(info->hash.digest, WC_SHA256_DIGEST_SIZE); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; } @@ -982,7 +1829,7 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" New AES Key: ckey:%p clen:%lu akey:%p alen:%u\n", c->aescbc_key,c->aescbc_keylen, aes->devKey, aes->keylen); - hexdump((void*)aes->devKey, aes->keylen); + _HexDump((void*)aes->devKey, aes->keylen); #endif /* Free the current key buffer if necessary */ if (c->aescbc_key != NULL) { @@ -992,7 +1839,7 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info, } /* Allocate key buffer */ - c->aescbc_key = XMALLOC(aes->keylen, NULL, NULL); + c->aescbc_key = (unsigned char*)XMALLOC(aes->keylen, NULL, NULL); if (c->aescbc_key == NULL) { #if defined(CCBVAULTIC_DEBUG) XPRINTF(" Failed to allocate new AES Key of size:%u\n", @@ -1036,9 +1883,9 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info, &tmpAesKey); #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VLT PutKey:%x\n", c->vlt_rc); - hexdump(c->aescbc_key, c->aescbc_keylen); + _HexDump((const char*)c->aescbc_key, c->aescbc_keylen); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; } @@ -1054,7 +1901,7 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info, #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" VLT InitAlgo:%x\n", c->vlt_rc); #endif - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; @@ -1083,7 +1930,7 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info, XPRINTF(" VLT Decrypt:%x\n", c->vlt_rc); #endif } - rc = translateError(c->vlt_rc); + rc = _TranslateError(c->vlt_rc); if (rc != 0) break; diff --git a/ccb_vaultic/ccb_vaultic.h b/ccb_vaultic/ccb_vaultic.h index f3d8d4db5..19e5f69f1 100644 --- a/ccb_vaultic/ccb_vaultic.h +++ b/ccb_vaultic/ccb_vaultic.h @@ -36,9 +36,98 @@ * compiled in the proper hardware configuration. */ +/* Fixed sizes and values */ +enum { + CCBVAULTIC_SERIAL_LEN = 8, + CCBVAULTIC_VERSION_LEN = 32, + + CCBVAULTIC_CMD_INFO = 0x8000, + CCBVAULTIC_CMD_LOADACTION = 0x8001, + CCBVAULTIC_CMD_PROVISIONACTION = 0x8002, + CCBVAULTIC_CMD_SELFTEST = 0x8003, + + CCBVAULTIC_INFO_LEN = 128, +}; + +/* Configuration choices */ +enum { + CCBVAULTIC_FAST_START_MS = 700, + CCBVAULTIC_SLOW_START_MS = 5000, + CCBVAULTIC_APDU_TIMEOUT_MS = 5000, + CCBVAULTIC_SPI_RATE_KHZ = 5000, +}; + + +/* Authenticated User: + * + */ +enum { + CCBVAULTIC_AUTH_ID_MIN = 0, + CCBVAULTIC_AUTH_ID_MAX = 7, + + CCBVAULTIC_AUTH_ROLE_NONE = 0, + CCBVAULTIC_AUTH_ROLE_MANUFACTURER = 1, + CCBVAULTIC_AUTH_ROLE_UNAPPROVED = 2, + CCBVAULTIC_AUTH_ROLE_APPROVED = 3, + + CCBVAULTIC_AUTH_KIND_NONE = 0, + CCBVAULTIC_AUTH_KIND_PIN = 1, + CCBVAULTIC_AUTH_KIND_SCP03 = 2, + CCBVAULTIC_AUTH_KIND_KDF = 3, + + CCBVAULTIC_AUTH_PIN_LEN_MIN = 0x4, + CCBVAULTIC_AUTH_PIN_LEN_MAX = 0x20, + + CCBVAULTIC_AUTH_MAC_LEN = 0x10, /* AES128 keys only */ + CCBVAULTIC_AUTH_ENC_LEN = 0x10, /* AES128 keys only */ + + CCBVAULTIC_AUTH_KDF_KEY_LEN_MIN = 0x10, + CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX = 0x40, + CCBVAULTIC_AUTH_KDF_LABEL_LEN_MIN = 0x0, + CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX = 0x40, +}; + +typedef struct { + int id; /* between CCBVAULTIC_AUTH_ID_MIN/MAX */ + int role; /* enum of CCBVAULTIC_AUTH_ROLE_xxx */ + int kind; /* enum of CCBVAULTIC_AUTH_KIND_xxx */ + union { /* based on kind */ + struct { + size_t pin_len; + char* pin; + } pin; + struct { + size_t mac_len; + char* mac; + size_t enc_len; + char* enc; + } scp03; + struct { + size_t key_len; + char* key; + size_t label_len; + char* label; + } kdf; + } auth; +} ccbVaultIc_Auth; + +typedef struct { + int startup_delay_ms; + int timeout_ms; + int spi_rate_khz; + + ccbVaultIc_Auth auth; +} ccbVaultIc_Config; + +/* Storage for default auth config. Declared in ccb_vaultic.c */ +extern ccbVaultIc_Config gDefaultConfig; + typedef struct { int initialized; + const ccbVaultIc_Config* config; int vlt_rc; + char vlt_serial[CCBVAULTIC_SERIAL_LEN]; + char vlt_version[CCBVAULTIC_VERSION_LEN]; /* Buffer to store message during SHA with will_copy flag set */ int hash_type; /* enum wc_HashType */ @@ -53,19 +142,110 @@ typedef struct { /* ccbVaultIc_Context static initializer */ #define CCBVAULTIC_CONTEXT_INITIALIZER \ { \ - .initialized = 0 \ + .initialized = 0, \ + .config = NULL \ } -/* Initialize the Wisekey VaultIC library and clear the context. + +enum { + CCBVAULTIC_FILE_NAME_LEN_MIN = 0x1, /* At least a NULL */ + CCBVAULTIC_FILE_NAME_LEN_MAX = 0x10, /* 16 byte limit for names */ + CCBVAULTIC_FILE_DATA_LEN_MAX = 0x10000, /* 16kB limit for files */ +}; +typedef struct { + int name_len; + char* name; /* Path, start with / */ + int data_len; + char* data; +} ccbVaultIc_File; + + +/* Provision Action + * Must authenticate as MANUFACTURER role first. Then invoke provision action: + * -sets chip to CREATION state: VltSetStatus(VLT_STATE_CREATION) + * -sets power on self test to self_test: VltSetConfig(...) + * -deletes all other users: VltManageAuthenticationData(...) + * -creates auth user using id, role, and auth kind + * -creates and copies file_count files from file[] with auth and current + * user id with all privs + * -sets chip to ACTIVATED state + */ +enum { + CCBVAULTIC_PROV_SELFTEST_OPTIONAL = 0, + CCBVAULTIC_PROV_SELFTEST_REQUIRED = 1, +}; + +/* Data provided to Provision action */ +typedef struct { + int self_test; + ccbVaultIc_Auth create; + int file_count; + ccbVaultIc_File *file; +} ccbVaultIc_Provision; + +/* Data provided to Load action */ +typedef struct { + int file_count; + ccbVaultIc_File* file; +} ccbVaultIc_Load; + +typedef struct { + int text_len; + char* text; +} ccbVaultIc_Info; + +typedef struct { + int index; + int label_len; + char* label; + int data_len; + char* data; +} ccbVaultIc_Nvm; + +/* Get a pointer to the default configuration data, which is used when the + * context passed into ccbVaultIc_Init has c->config == NULL. This will happen + * when the the CryptoCb_Register() is invoked with a NULL context. + */ +int ccbVaultIc_GetDefaultConfig(ccbVaultIc_Config* *out_c); + +/* Initialize the VaultIC library and clear the context. * Returns: 0 on success * BAD_FUNC_ARGS with NULL context * WC_INIT_E on error initializing the VaultIC. * c->vlt_rc will have error code */ -int ccbVaultIc_Init(ccbVaultIc_Context *c); +int ccbVaultIc_Init( ccbVaultIc_Context *c); + +/* Close the VaultIC library. */ +void ccbVaultIc_Cleanup( ccbVaultIc_Context *c); -/* Close the Wisekey VaultIC library. */ -void ccbVaultIc_Cleanup(ccbVaultIc_Context *c); +/* Create a file on the VaultIc, accessible by only the user and manufacturer */ +int ccbVaultIc_CreateUserFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f, + int userId, int manuId); + +/* Delete a file on the VaultIC*/ +int ccbVaultIc_DeleteFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f); + +/* Write file data into the vaultic from the file struct */ +int ccbVaultIc_WriteFile( ccbVaultIc_Context *c, + const ccbVaultIc_File *f); + +/* Read file data from the vaultic into the file struct */ +int ccbVaultIc_ReadFile( ccbVaultIc_Context *c, + ccbVaultIc_File *f); + +/* Perform the load action as the currently authed user */ +int ccbVaultIc_LoadAction( ccbVaultIc_Context *c, + ccbVaultIc_Load *l); + +/* Perform the provision action as the currently authed user */ +int ccbVaultIc_ProvisionAction( ccbVaultIc_Context *c, + const ccbVaultIc_Provision *p); + +/* Perform selftest. Chip will timeout on failure */ +int ccbVaultIc_SelfTest( ccbVaultIc_Context *c); #ifdef WOLF_CRYPTO_CB #include "wolfssl/wolfcrypt/cryptocb.h" /* For wc_CryptInfo */ @@ -77,7 +257,7 @@ void ccbVaultIc_Cleanup(ccbVaultIc_Context *c); * CCBVAULTIC420_DEVID, * ccbVaultIc_CryptoCb, * &ctx); - * wc_Aes aes={0}; + * wc_Aes aes; * wc_AesInit(&aes, NULL, CCBVAULTIC420_DEVID); * Returns: 0 on success * CRYPTOCB_UNAVAILABLE if not initialized or not implemented @@ -88,6 +268,34 @@ int ccbVaultIc_CryptoCb(int devId, void* ctx); #endif /* WOLF_CRYPTO_CB */ + + +#define CCBVAULTIC_AUTH_ID_DEFAULT 1 +#define CCBVAULTIC_SCP03_MAC_DEFAULT \ + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" +#define CCBVAULTIC_SCP03_ENC_DEFAULT \ + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" +#define CCBVAULTIC_AUTH_DEFAULT \ + { \ + .id = CCBVAULTIC_AUTH_ID_DEFAULT, \ + .role = CCBVAULTIC_AUTH_ROLE_UNAPPROVED, \ + .kind = CCBVAULTIC_AUTH_KIND_SCP03, \ + .auth.scp03 = { \ + .mac_len = sizeof(CCBVAULTIC_SCP03_MAC_DEFAULT) - 1, \ + .mac = CCBVAULTIC_SCP03_MAC_DEFAULT, \ + .enc_len = sizeof(CCBVAULTIC_SCP03_ENC_DEFAULT) - 1, \ + .enc = CCBVAULTIC_SCP03_ENC_DEFAULT, \ + } \ + } + +#define CCBVAULTIC_CONFIG_DEFAULT \ + { \ + .startup_delay_ms = CCBVAULTIC_FAST_START_MS, \ + .timeout_ms = CCBVAULTIC_APDU_TIMEOUT_MS, \ + .spi_rate_khz = CCBVAULTIC_SPI_RATE_KHZ, \ + .auth = CCBVAULTIC_AUTH_DEFAULT, \ + } + #endif /* HAVE_CCBVAULTIC */ #endif /* CCB_VAULTIC_H_ */ diff --git a/ccb_vaultic/ccb_vaultic_config.h b/ccb_vaultic/ccb_vaultic_config.h new file mode 100644 index 000000000..87dba95e3 --- /dev/null +++ b/ccb_vaultic/ccb_vaultic_config.h @@ -0,0 +1,299 @@ +/* + * ccb_vaultic_config.h + * + * Copyright (C) 2023 wolfSSL Inc. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef CCB_VAULTIC_CONFIG_H +#define CCB_VAULTIC_CONFIG_H + +#include "ccb_vaultic.h" + +#ifdef HAVE_CCBVAULTIC + +/* + * Example configuration structures */ + +/* Configuration choices */ +enum { + _KDF_ID = 0, + _USER_ID = 1, + _MANU_ID = 7, +}; + +#define _KDF_KEY \ + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" \ + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" +#define _KDF_LABEL \ + "KDF Label" + +#define _USER_MAC \ + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" +#define _USER_ENC \ + "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" + +#define _MANU_PIN \ + "\x00\x01\x02\x03\x04\x05\x06\x07" + +#define _KEY_NAME "/key.pem" +#define _CRT_NAME "/crt.pem" +#define _CA_NAME "/ca.pem" + +/* Storage for loaded files */ +char gLoadKey_data[CCBVAULTIC_FILE_DATA_LEN_MAX]; +char gLoadCrt_data[CCBVAULTIC_FILE_DATA_LEN_MAX]; +char gLoadCa_data[CCBVAULTIC_FILE_DATA_LEN_MAX]; + +/* Filthy preprocessor trick... */ +#define QUOTE(...) #__VA_ARGS__ + +/* From wolfssl/certs/client-key.pem */ +char gProvKey_data[] = QUOTE( +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAwwPRK/45pDJFO1PIhCsqfHSavaoqUgdH1qY2sgcyjtC6aXvG +w0Se1IFI/S1oootnu6F1yDYsStIb94u6zw357+zxgR57mwNHmr9lzH9lJGmm6BSJ +W+Q098WwFJP1Z3s6enjhAVZWkaYTQo3SPECcTO/Rht83URsMoTv18aNKNeThzpbf +G36/TpfQEOioCDCBryALQxTFdGe0MoJvjYbCiECZNoO6HkByIhfXUmUkc7DO7xnN +rv94bHvAEgPUTnINUG07ozujmV6dyNkMhbPZitlUJttt+qy7/yVMxNF59HHThkAY +E7BjtXJOMMSXhIYtVi/XFfd/wK71/Fvl+6G60wIDAQABAoIBAQCi5thfEHFkCJ4u +bdFtHoXSCrGMR84sUWqgEp5T3pFMHW3qWXvyd6rZxtmKq9jhFuRjJv+1bBNZuOOl +yHIXLgyfb+VZP3ZvSbERwlouFikN3reO3EDVou7gHqH0vpfbhmOWFM2YCWAtMHac +PM3miO5HknkLWgDiXl8RfH35CLcgBokqXf0AqyLh8LO8JKleJg4fAC3+IZpTW23T +K6uUgmhDNtj2L8Yi/LVBXQ0zYOqkfX7oS1WRVtNcV48flBcvqt7pnqj0z4pMjqDk +VnOyz0+GxWk88yQgi1yWDPprEjuaZ8HfxpaypdWSDZsJQmgkEEXUUOQXOUjQNYuU +bRHej8pZAoGBAOokp/lpM+lx3FJ9iCEoL0neunIW6cxHeogNlFeEWBY6gbA/os+m +bB6wBikAj+d3dqzbysfZXps/JpBSrvw4kAAUu7QPWJTnL2p+HE9BIdQxWR9OihqN +p1dsItjl9H4yphDLZKVVA4emJwWMw9e2J7JNujDaR49U0z2LhI2UmFilAoGBANU4 +G8OPxZMMRwtvNZLFsI1GyJIYj/WACvfvof6AubUqusoYsF2lB9CTjdicBBzUYo6m +JoEB/86KKmM0NUCqbYDeiSNqV02ebq2TTlaQC22dc4sMric93k7wqsVseGdslFKc +N2dsLe+7r9+mkDzER8+Nlp6YqbSfxaZQ3LPw+3QXAoGAXoMJYr26fKK/QnT1fBzS +ackEDYV+Pj0kEsMYe/Mp818OdmxZdeRBhGmdMvPNIquwNbpKsjzl2Vi2Yk9d3uWe +CspTsiz3nrNrClt5ZexukU6SIPb8/Bbt03YM4ux/smkTa3gOWkZktF63JaBadTpL +78c8Pvf9JrggxJkKmnO+wxkCgYEAukSTFKw0GTtfkWCs97TWgQU2UVM96GXcry7c +YT7Jfbh/h/A7mwOCKTfOck4R1bHBDAegmZFKjX/sec/xObXphexi99p9vGRNIjwO +8tZR9YfYmcARIF0PKf1b4q7ZHNkhVm38hNBf7RAVHBgh58Q9S9fQnmqVzyLJA3ue +42AB/C8CgYAR0EvPG2e5nxB1R4ZlrjHCxjCsWQZQ2Q+1cAb38NPIYnyo2m72IT/T +f1/qiqs/2Spe81HSwjA34y2jdQ0eTSE01VdwXIm/cuxKbmjVzRh0M06MOkWP5pZA +62P5GYY6Ud2JS7Dz+Z9dKJU4vjWrylznk1M0oUVdEzllQkahn831vw== +-----END RSA PRIVATE KEY----- +); + +/* From wolfssl/certs/client-cert.pem */ +char gProvCrt_data[] = QUOTE( +-----BEGIN CERTIFICATE----- +MIIFHTCCBAWgAwIBAgIUc/tU1gN9TAeE4gARjN2Q3EiN6lMwDQYJKoZIhvcNAQEL +BQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNVBAsMEFByb2dyYW1t +aW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJ +ARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMjEyMTYyMTE3NDlaFw0yNTA5MTEyMTE3 +NDlaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwH +Qm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFt +bWluZy0yMDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0B +CQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDDA9Er/jmkMkU7U8iEKyp8dJq9qipSB0fWpjayBzKO0Lppe8bDRJ7UgUj9 +LWiii2e7oXXINixK0hv3i7rPDfnv7PGBHnubA0eav2XMf2UkaaboFIlb5DT3xbAU +k/Vnezp6eOEBVlaRphNCjdI8QJxM79GG3zdRGwyhO/Xxo0o15OHOlt8bfr9Ol9AQ +6KgIMIGvIAtDFMV0Z7Qygm+NhsKIQJk2g7oeQHIiF9dSZSRzsM7vGc2u/3hse8AS +A9ROcg1QbTujO6OZXp3I2QyFs9mK2VQm2236rLv/JUzE0Xn0cdOGQBgTsGO1ck4w +xJeEhi1WL9cV93/ArvX8W+X7obrTAgMBAAGjggFPMIIBSzAdBgNVHQ4EFgQUM9hF +Ztdohxh+VA1wJ5HHJteFZcAwgd4GA1UdIwSB1jCB04AUM9hFZtdohxh+VA1wJ5HH +JteFZcChgaSkgaEwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAw +DgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNVBAsM +EFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0G +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIUc/tU1gN9TAeE4gARjN2Q3EiN +6lMwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAAATAd +BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEB +ADbLvMVSmmbNkU2PJ5+zZIAOZLTLGs11noJ8VWfYn5CjNJaZQ/dJU6JYhaCzg0+v +uBWKiB7zYPR8lLVYaPEqE4A0wm+l+H52FoFPNovDWb1R3WCH1x2WRGkHPI8oVrER +XE6BP1cl/WXdB88XCgF+Tj+Oc9v+9PLF/6N2qHRGLkcNsO0KwMUKZdPcYrLgHo69 +872vr2aENpLiO4DQV6ZBo2LRpm0UbM2CscHBNVWuWUmoJlK97xssH505BNKCoGs5 +cVkzgrpVbJfyG1vgTeLPiecmuCxsn4PW7U4vdakwTgGVDU+DXsivf2fqU7/Kmx/U +/zaXAnGOM97iWCeqcAxb3g4= +-----END CERTIFICATE----- +); + +/* From wolfssl/certs/ca-cert.pem */ +char gProvCa_data[] = QUOTE( +-----BEGIN CERTIFICATE----- +MIIE/zCCA+egAwIBAgIULIDO20edB2aSPWjXyqyQT8ppQUswDQYJKoZIhvcNAQEL +BQAwgZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC +b3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEY +MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv +bGZzc2wuY29tMB4XDTIyMTIxNjIxMTc0OVoXDTI1MDkxMTIxMTc0OVowgZQxCzAJ +BgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREw +DwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwP +d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvwzKLRSyHoRCW804H0ry +TXUQ8bY1n9/KfQOY06zeA2buKvHYsH1uB1QLEJghTYDLEiDnzE/eRX3Jcncy6sqQ +u2lSEAMvqPOVxfGLYlYb72dvpBBBla0Km+OlwLDScHZQMFuo6AgsfO2nonqNOCkc +rMft8nyVsJWCfUlcOM13Je+9gHVTlDw9ymNbnxW10x0TLxnRPNt2Osy4fcnlwtfa +QG/YIdxzG0ItU5z+Gvx9q3o2P5jehHwFZ85qFDiHqfGMtWjLaH9xICv1oGP1Vi+j +JtK3b7FaF9c4mQj+k1hv/sMTSQgWC6dNZwBSMWcjTpjtUUUduQTZC+zYKLNLve02 +eQIDAQABo4IBRTCCAUEwHQYDVR0OBBYEFCeOZxF0wyYdP+0zY7Ok2B0w5ejVMIHU +BgNVHSMEgcwwgcmAFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYD +VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G +A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 +dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIU +LIDO20edB2aSPWjXyqyQT8ppQUswDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtl +eGFtcGxlLmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +DQYJKoZIhvcNAQELBQADggEBAK6wpDWOihum67OiV886H9xuvNLQpkqPiApudNXR +fNFEsdQ7FwMJWkbtCAjP8f0gB2fAl+w183XKIGGYPvVNvuaddR7kA62Mph497OQa +klv5o62Dyk/Nqji7bq6t+qdG8Ytz7AkjvPIY5beShj6kdWDHPQ8/gwDDBgic0VTW +um2VPTShviSRzCADEVtyHNRl0BGIdSYEJu9mcOY7OIecU3EbCVFwUJlMMQxiRFcw +YAT8EiyjJLT3EdUOtSEL7YYRZ002+legWVUhs23kd17sfvAJE46ZmLLhgrZLPg9B +pgzNSZl+5IrLN+1Tz4ZdqSao5QElWrS8JTXx+lpcztS4miw= +-----END CERTIFICATE----- +); + +/*************** Generated structures *******************/ + +/* Forward declarations, for readability */ +const ccbVaultIc_Config gKdfConfig; +const ccbVaultIc_Config gUserConfig; +const ccbVaultIc_Config gManuConfig; + +const ccbVaultIc_Provision gProvision; +ccbVaultIc_Load gLoad; + +/* KDF Auth */ +#define _KDF \ + { \ + .id = _KDF_ID, \ + .role = CCBVAULTIC_AUTH_ROLE_APPROVED, \ + .kind = CCBVAULTIC_AUTH_KIND_KDF, \ + .auth.kdf = \ + { \ + .key_len = sizeof(_KDF_KEY) - 1, \ + .key = _KDF_KEY, \ + .label_len = sizeof(_KDF_LABEL) - 1, \ + .label = _KDF_LABEL, \ + } \ + } + +/* User Auth */ +#define _USER \ + { \ + .id = _USER_ID, \ + .role = CCBVAULTIC_AUTH_ROLE_UNAPPROVED, \ + .kind = CCBVAULTIC_AUTH_KIND_SCP03, \ + .auth.scp03 = \ + { \ + .mac_len = sizeof(_USER_MAC) - 1, \ + .mac = _USER_MAC, \ + .enc_len = sizeof(_USER_ENC) - 1, \ + .enc = _USER_ENC, \ + } \ + } + +/* Manu Auth */ +#define _MANU \ + { \ + .id = _MANU_ID, \ + .role = CCBVAULTIC_AUTH_ROLE_MANUFACTURER, \ + .kind = CCBVAULTIC_AUTH_KIND_PIN, \ + .auth.pin = \ + { \ + .pin_len = sizeof(_MANU_PIN) - 1, \ + .pin = _MANU_PIN, \ + } \ + } + +const ccbVaultIc_Config gKdfConfig = + { + .startup_delay_ms = CCBVAULTIC_FAST_START_MS, + .timeout_ms = CCBVAULTIC_APDU_TIMEOUT_MS, + .spi_rate_khz = CCBVAULTIC_SPI_RATE_KHZ, + .auth = _KDF, + }; + +const ccbVaultIc_Config gUserConfig = + { + .startup_delay_ms = CCBVAULTIC_FAST_START_MS, + .timeout_ms = CCBVAULTIC_APDU_TIMEOUT_MS, + .spi_rate_khz = CCBVAULTIC_SPI_RATE_KHZ, + .auth = _USER, + }; + +const ccbVaultIc_Config gManuConfig = + { + .startup_delay_ms = CCBVAULTIC_FAST_START_MS, + .timeout_ms = CCBVAULTIC_APDU_TIMEOUT_MS, + .spi_rate_khz = CCBVAULTIC_SPI_RATE_KHZ, + .auth = _MANU, + }; + +ccbVaultIc_File gLoadFiles[] = + { + { + .name_len = sizeof(_KEY_NAME), + .name = _KEY_NAME, + .data_len = sizeof(gLoadKey_data), + .data = gLoadKey_data, + }, + { + .name_len = sizeof(_CRT_NAME), + .name = _CRT_NAME, + .data_len = sizeof(gLoadCrt_data), + .data = gLoadCrt_data, + }, + { + .name_len = sizeof(_CA_NAME), + .name = _CA_NAME, + .data_len = sizeof(gLoadCa_data), + .data = gLoadCa_data, + }, + }; + +ccbVaultIc_Load gLoad = + { + .file_count = sizeof(gLoadFiles) / sizeof(gLoadFiles[0]), + .file = gLoadFiles, + }; + +const ccbVaultIc_File gProvFiles[] = + { + { + .name_len = sizeof(_KEY_NAME), + .name = _KEY_NAME, + .data_len = sizeof(gProvKey_data), + .data = gProvKey_data, + }, + { + .name_len = sizeof(_CRT_NAME), + .name = _CRT_NAME, + .data_len = sizeof(gProvCrt_data), + .data = gProvCrt_data, + }, + { + .name_len = sizeof(_CA_NAME), + .name = _CA_NAME, + .data_len = sizeof(gProvCa_data), + .data = gProvCa_data, + }, + }; + +const ccbVaultIc_Provision gProvision = + { + .self_test = CCBVAULTIC_PROV_SELFTEST_OPTIONAL, + .create = _USER, + .file_count = sizeof(gProvFiles) / sizeof(gProvFiles[0]), + .file = gProvFiles, + }; + +#endif /* HAVE_CCBVAULTIC */ + +#endif /* CCB_VAULTIC_CONFIG_H_ */ diff --git a/ccb_vaultic/com_wolfssl_ccbvaultic_ccbVaultIc.c b/ccb_vaultic/com_wolfssl_ccbvaultic_ccbVaultIc.c new file mode 100644 index 000000000..867e6ce51 --- /dev/null +++ b/ccb_vaultic/com_wolfssl_ccbvaultic_ccbVaultIc.c @@ -0,0 +1,367 @@ +#include + +/* wolfSSL configuration */ +#ifndef WOLFSSL_USER_SETTINGS + #include "wolfssl/options.h" +#endif +#include "wolfssl/wolfcrypt/settings.h" + +/* wolfCrypt includes */ +#include "wolfssl/wolfcrypt/cryptocb.h" /* For wc_cryptInfo */ +#include "wolfssl/wolfcrypt/error-crypt.h" /* For error values */ + +#include "ccb_vaultic.h" + +#ifdef HAVE_CCBVAULTIC +static char defaultAuthStorage1[CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX]; +static char defaultAuthStorage2[CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX]; +static char fileNames[3][CCBVAULTIC_FILE_NAME_LEN_MAX]; +#endif + +/* Prototypes are in ccbVaultIc.java */ + +JNIEXPORT jint JNICALL Java_com_wolfssl_ccbvaultic_ccbVaultIc_GetInfoText ( + JNIEnv* jenv, jobject jcl, + jint devId, jobject out, jlongArray outSz) +{ +#ifndef HAVE_CCBVAULTIC + (void)jenv; (void)jcl; (void)devId; (void)out; (void)outSz; + return (jint)CRYPTOCB_UNAVAILABLE; +#else + (void)jcl; + int rc = 0; + jlong jSize = 0; + ccbVaultIc_Info info; + + XMEMSET(&info, 0, sizeof(info)); + + /* Ok if this buffer is NULL */ + info.text = (*jenv)->GetDirectBufferAddress(jenv, out); + + /* Ok if this length is 0 */ + (*jenv)->GetLongArrayRegion(jenv, outSz, 0, 1, &jSize); + info.text_len = (int)jSize; + + /* Invoke the callback */ + rc = wc_CryptoCb_Command((int)devId, CCBVAULTIC_CMD_INFO, (void*) &info, NULL); + if(rc == 0) { + /* Update the output length */ + jSize = info.text_len; + (*jenv)->SetLongArrayRegion(jenv, outSz, 0, 1, (jlong*)&jSize); + } + return (jint)rc; +#endif +} + + +JNIEXPORT jint JNICALL Java_com_wolfssl_ccbvaultic_ccbVaultIc_UpdateDefaultAuth( + JNIEnv *jenv, jobject jcl, + jint id, jint role, jint kind, + jobject in1, jlongArray in1_sz, + jobject in2, jlongArray in2_sz) +{ +#ifndef HAVE_CCBVAULTIC + (void)jenv; (void)jcl; (void)id; (void)role; (void)kind; + (void)in1; (void)in1_sz; (void)in2; (void)in2_sz; + return (jint)CRYPTOCB_UNAVAILABLE; +#else + int rc = 0; + + char *in1p = NULL; + char *in2p = NULL; + jlong in1Len = 0; + jlong in2Len = 0; + + if (in1 != NULL) in1p = (*jenv)->GetDirectBufferAddress(jenv, in1); + if (in2 != NULL) in2p = (*jenv)->GetDirectBufferAddress(jenv, in2); + if (in1_sz != NULL) (*jenv)->GetLongArrayRegion(jenv, in1_sz, 0, 1, &in1Len); + if (in2_sz != NULL) (*jenv)->GetLongArrayRegion(jenv, in2_sz, 0, 1, &in2Len); + + switch((int)kind) { + case CCBVAULTIC_AUTH_KIND_NONE: + { + gDefaultConfig.auth.id = (int)id; + gDefaultConfig.auth.role = (int)role; + gDefaultConfig.auth.kind = CCBVAULTIC_AUTH_KIND_NONE; + rc = 0; + }; break; + case CCBVAULTIC_AUTH_KIND_PIN: { + if((in1p == NULL) || (in1Len < CCBVAULTIC_AUTH_PIN_LEN_MIN) || + (in1Len > CCBVAULTIC_AUTH_PIN_LEN_MAX)) { + rc = BAD_FUNC_ARG; + break; + } + /* Save updated info */ + XMEMCPY(defaultAuthStorage1, in1p, in1Len); + + gDefaultConfig.auth.id = (int)id; + gDefaultConfig.auth.role = (int)role; + gDefaultConfig.auth.kind = CCBVAULTIC_AUTH_KIND_PIN; + gDefaultConfig.auth.auth.pin.pin = defaultAuthStorage1; + gDefaultConfig.auth.auth.pin.pin_len = in1Len; + rc = 0; + };break; + case CCBVAULTIC_AUTH_KIND_SCP03: { + if((in1p == NULL) || (in1Len != CCBVAULTIC_AUTH_MAC_LEN) || + (in2p == NULL) || (in2Len != CCBVAULTIC_AUTH_ENC_LEN)) { + rc = BAD_FUNC_ARG; + break; + } + /* Save updated info */ + XMEMCPY(defaultAuthStorage1, in1p, CCBVAULTIC_AUTH_MAC_LEN); + XMEMCPY(defaultAuthStorage2, in2p, CCBVAULTIC_AUTH_ENC_LEN); + + gDefaultConfig.auth.id = (int)id; + gDefaultConfig.auth.role = (int)role; + gDefaultConfig.auth.kind = CCBVAULTIC_AUTH_KIND_SCP03; + gDefaultConfig.auth.auth.scp03.mac = defaultAuthStorage1; + gDefaultConfig.auth.auth.scp03.mac_len = in1Len; + gDefaultConfig.auth.auth.scp03.enc = defaultAuthStorage2; + gDefaultConfig.auth.auth.scp03.enc_len = in2Len; + rc = 0; + };break; + case CCBVAULTIC_AUTH_KIND_KDF: { + if((in1p == NULL) || (in1Len < CCBVAULTIC_AUTH_KDF_KEY_LEN_MIN) || + (in1Len > CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX) || + (in2p == NULL) || (in2Len < CCBVAULTIC_AUTH_KDF_LABEL_LEN_MIN) || + (in2Len > CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX)) { + rc = BAD_FUNC_ARG; + break; + } + /* Save updated info */ + XMEMCPY(defaultAuthStorage1, in1p, in1Len); + XMEMCPY(defaultAuthStorage2, in2p, in2Len); + + gDefaultConfig.auth.id = (int)id; + gDefaultConfig.auth.role = (int)role; + gDefaultConfig.auth.kind = CCBVAULTIC_AUTH_KIND_KDF; + gDefaultConfig.auth.auth.kdf.key = defaultAuthStorage1; + gDefaultConfig.auth.auth.kdf.key_len = in1Len; + gDefaultConfig.auth.auth.kdf.label = defaultAuthStorage2; + gDefaultConfig.auth.auth.kdf.label_len = in2Len; + rc = 0; + };break; + default: + rc = BAD_FUNC_ARG; + } + return (jint)rc; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_ccbvaultic_ccbVaultIc_ProvisionAction( + JNIEnv *jenv, jobject jcl, + jint devId, jboolean selftest, + jint id, jint role, jint kind, + jobject userin1, jlongArray userin1_sz, + jobject userin2, jlongArray userin2_sz, + jstring in_name1, jobject in1, jlongArray in1_sz, + jstring in_name2, jobject in2, jlongArray in2_sz, + jstring in_name3, jobject in3, jlongArray in3_sz) +{ +#ifndef HAVE_CCBVAULTIC + (void)jenv; (void)jcl; (void)devId; (void)selftest; + (void)id; (void)role; (void)kind; + (void)userin1; (void)userin1_sz; + (void)userin2; (void)userin2_sz; + (void)in_name1; (void)in1; (void)in1_sz; + (void)in_name2; (void)in2; (void)in2_sz; + (void)in_name3; (void)in3; (void)in3_sz; + return (jint)CRYPTOCB_UNAVAILABLE; +#else + int rc = 0; + jlong jSize; + const char *name; + ccbVaultIc_Provision p; + ccbVaultIc_File files[3]; + char filenames[3][CCBVAULTIC_FILE_NAME_LEN_MAX]; + + char *userin1p = NULL; + char *userin2p = NULL; + jlong userin1Len = 0; + jlong userin2Len = 0; + + if (in1 != NULL) userin1p = (*jenv)->GetDirectBufferAddress(jenv, userin1); + if (in2 != NULL) userin2p = (*jenv)->GetDirectBufferAddress(jenv, userin2); + if (in1_sz != NULL) (*jenv)->GetLongArrayRegion(jenv, userin1_sz, 0, 1, &userin1Len); + if (in2_sz != NULL) (*jenv)->GetLongArrayRegion(jenv, userin2_sz, 0, 1, &userin2Len); + + XMEMSET(&p, 0, sizeof(p)); + XMEMSET(files, 0, sizeof(files)); + XMEMSET(filenames, 0, sizeof(filenames)); + + p.self_test = (int)selftest; + p.create.id = (int)id; + p.create.role = (int)role; + p.create.kind = (int)kind; + p.file_count = 3; + p.file = files; + + switch(p.create.kind) { + case CCBVAULTIC_AUTH_KIND_KDF: { + if((userin1p == NULL) || (userin1Len < CCBVAULTIC_AUTH_KDF_KEY_LEN_MIN) || + (userin1Len > CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX) || + (userin2p == NULL) || (userin2Len < CCBVAULTIC_AUTH_KDF_LABEL_LEN_MIN) || + (userin2Len > CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX)) { + rc = BAD_FUNC_ARG; + break; + } + p.create.auth.kdf.key = userin1p; + p.create.auth.kdf.key_len = userin1Len; + p.create.auth.kdf.label = userin2p; + p.create.auth.kdf.label_len = userin2Len; + };break; + + case CCBVAULTIC_AUTH_KIND_SCP03: { + if((userin1p == NULL) || (userin1Len != CCBVAULTIC_AUTH_MAC_LEN) || + (userin2p == NULL) || (userin2Len != CCBVAULTIC_AUTH_ENC_LEN)) { + rc = BAD_FUNC_ARG; + break; + } + p.create.auth.scp03.mac = userin1p; + p.create.auth.scp03.mac_len = userin1Len; + p.create.auth.scp03.enc = userin2p; + p.create.auth.scp03.enc_len = userin2Len; + };break; + + case CCBVAULTIC_AUTH_KIND_PIN: + case CCBVAULTIC_AUTH_KIND_NONE: + default: + rc = BAD_FUNC_ARG; + } + if(rc == 0) { + //Set the file data + if ((in_name1 != NULL) && (in1 != NULL) && (in1_sz != NULL)) { + name = (*jenv)->GetStringUTFChars(jenv, in_name1, NULL); + if (name != NULL) { + p.file[0].name_len = XSTRLEN(name); + p.file[0].name = XMEMCPY(filenames[0], name, p.file[0].name_len); + (*jenv)->ReleaseStringUTFChars(jenv, in_name1, name); + (*jenv)->GetLongArrayRegion(jenv, in1_sz, 0, 1, &jSize); + p.file[0].data_len = jSize; + p.file[0].data = (*jenv)->GetDirectBufferAddress(jenv, in1); + } + } + if ((in_name2 != NULL) && (in2 != NULL) && (in2_sz != NULL)) { + name = (*jenv)->GetStringUTFChars(jenv, in_name2, NULL); + if (name != NULL) { + p.file[1].name_len = XSTRLEN(name); + p.file[1].name = XMEMCPY(filenames[1], name, p.file[1].name_len); + (*jenv)->ReleaseStringUTFChars(jenv, in_name2, name); + (*jenv)->GetLongArrayRegion(jenv, in2_sz, 0, 1, &jSize); + p.file[1].data_len = jSize; + p.file[1].data = (*jenv)->GetDirectBufferAddress(jenv, in2); + } + } + if ((in_name3 != NULL) && (in3 != NULL) && (in3_sz != NULL)) { + name = (*jenv)->GetStringUTFChars(jenv, in_name3, NULL); + if (name != NULL) { + p.file[2].name_len = XSTRLEN(name); + p.file[2].name = XMEMCPY(filenames[2], name, p.file[2].name_len); + (*jenv)->ReleaseStringUTFChars(jenv, in_name3, name); + (*jenv)->GetLongArrayRegion(jenv, in3_sz, 0, 1, &jSize); + p.file[2].data_len = jSize; + p.file[2].data = (*jenv)->GetDirectBufferAddress(jenv, in3); + } + } + /* Invoke the callback */ + rc = wc_CryptoCb_Command((int)devId, CCBVAULTIC_CMD_PROVISIONACTION, (void*) &p, NULL); + } + return (jint)rc; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_ccbvaultic_ccbVaultIc_LoadAction( + JNIEnv *jenv, jobject jcl, + jint devId, + jstring in_name1, jobject in1, jlongArray in1_sz, + jstring in_name2, jobject in2, jlongArray in2_sz, + jstring in_name3, jobject in3, jlongArray in3_sz) +{ +#ifndef HAVE_CCBVAULTIC + (void)jenv; (void)jcl; (void)devId; + (void)in_name1; (void)in1; (void)in1_sz; + (void)in_name2; (void)in2; (void)in2_sz; + (void)in_name3; (void)in3; (void)in3_sz; + return (jint)CRYPTOCB_UNAVAILABLE; +#else + int rc = 0; + jlong jSize; + const char* name; + ccbVaultIc_Load l; + ccbVaultIc_File files[3]; + char filenames[3][CCBVAULTIC_FILE_NAME_LEN_MAX]; + + XMEMSET(&l, 0, sizeof(l)); + XMEMSET(files, 0, sizeof(files)); + XMEMSET(filenames, 0, sizeof(filenames)); + + l.file_count = 3; + l.file = files; + + //Set the file data + if ((in_name1 != NULL) && (in1 != NULL) && (in1_sz != NULL)) { + name = (*jenv)->GetStringUTFChars(jenv, in_name1, NULL); + if (name != NULL) { + l.file[0].name_len = XSTRLEN(name); + l.file[0].name = XMEMCPY(filenames[0], name, l.file[0].name_len); + (*jenv)->ReleaseStringUTFChars(jenv, in_name1, name); + (*jenv)->GetLongArrayRegion(jenv, in1_sz, 0, 1, &jSize); + l.file[0].data_len = jSize; + l.file[0].data = (*jenv)->GetDirectBufferAddress(jenv, in1); + } + } + if ((in_name2 != NULL) && (in2 != NULL) && (in2_sz != NULL)) { + name = (*jenv)->GetStringUTFChars(jenv, in_name2, NULL); + if (name != NULL) { + l.file[1].name_len = XSTRLEN(name); + l.file[1].name = XMEMCPY(filenames[1], name, l.file[1].name_len); + (*jenv)->ReleaseStringUTFChars(jenv, in_name2, name); + (*jenv)->GetLongArrayRegion(jenv, in2_sz, 0, 1, &jSize); + l.file[1].data_len = jSize; + l.file[1].data = (*jenv)->GetDirectBufferAddress(jenv, in2); + } + } + if ((in_name3 != NULL) && (in3 != NULL) && (in3_sz != NULL)) { + name = (*jenv)->GetStringUTFChars(jenv, in_name3, NULL); + if (name != NULL) { + l.file[2].name_len = XSTRLEN(name); + l.file[2].name = XMEMCPY(filenames[2], name, l.file[2].name_len); + (*jenv)->ReleaseStringUTFChars(jenv, in_name3, name); + (*jenv)->GetLongArrayRegion(jenv, in3_sz, 0, 1, &jSize); + l.file[2].data_len = jSize; + l.file[2].data = (*jenv)->GetDirectBufferAddress(jenv, in3); + } + } + + rc = wc_CryptoCb_Command((int)devId, CCBVAULTIC_CMD_LOADACTION, (void*) &l, NULL); + if(rc == 0) { + /* Update the output lengths */ + jSize = l.file[0].data_len; + if(in1_sz != NULL) (*jenv)->SetLongArrayRegion(jenv, in1_sz, 0, 1, (jlong*)&jSize); + jSize = l.file[1].data_len; + if(in2_sz != NULL) (*jenv)->SetLongArrayRegion(jenv, in2_sz, 0, 1, (jlong*)&jSize); + jSize = l.file[2].data_len; + if(in3_sz != NULL) (*jenv)->SetLongArrayRegion(jenv, in3_sz, 0, 1, (jlong*)&jSize); + } + + return rc; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_ccbvaultic_ccbVaultIc_PerformSelfTest( + JNIEnv *jenv, jobject jcl, + jint devId) +{ +#ifndef HAVE_CCBVAULTIC + (void)jenv; (void)jcl; (void)devId; + return (jint)CRYPTOCB_UNAVAILABLE; +#else + (void)jcl; + int rc = 0; + + /* Invoke the callback */ + rc = wc_CryptoCb_Command((int)devId, CCBVAULTIC_CMD_SELFTEST, NULL, NULL); + return (jint)rc; + +#endif +} \ No newline at end of file diff --git a/ccb_vaultic/java/com/wolfssl/ccbvaultic/ccbVaultIc.java b/ccb_vaultic/java/com/wolfssl/ccbvaultic/ccbVaultIc.java new file mode 100644 index 000000000..5bf9e432c --- /dev/null +++ b/ccb_vaultic/java/com/wolfssl/ccbvaultic/ccbVaultIc.java @@ -0,0 +1,447 @@ +package com.wolfssl.ccbvaultic; + +import android.util.Base64; + +import java.io.ByteArrayInputStream; +import java.nio.ByteBuffer; +import java.security.BasicPermission; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.EncodedKeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Arrays; +import java.util.Collection; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManager; + +public class ccbVaultIc { + static { + System.loadLibrary("ccbvaulticjni"); + } + + /* From ccb_vaultic.h */ + public static final int CCBVAULTIC_SERIAL_LEN = 8; + public static final int CCBVAULTIC_VERSION_LEN = 32; + + public static final int CCBVAULTIC_CMD_INFO = 0x8000; + public static final int CCBVAULTIC_CMD_LOADACTION = 0x8001; + public static final int CCBVAULTIC_CMD_PROVISIONACTION = 0x8002; + public static final int CCBVAULTIC_CMD_SELFTEST = 0x8003; + + public static final int CCBVAULTIC_INFO_LEN = 128; + public static final int CCBVAULTIC_FAST_START_MS = 700; + public static final int CCBVAULTIC_SLOW_START_MS = 5000; + public static final int CCBVAULTIC_APDU_TIMEOUT_MS = 5000; + public static final int CCBVAULTIC_SPI_RATE_KHZ = 5000; + public static final int CCBVAULTIC_FILE_NAME_LEN_MIN = 0x1; /* At least a NULL */ + public static final int CCBVAULTIC_FILE_NAME_LEN_MAX = 0x10; /* 16 byte limit for names */ + public static final int CCBVAULTIC_FILE_DATA_LEN_MAX = 0x10000; /* 16kB limit for files */ + public static final int CCBVAULTIC_AUTH_ID_MIN = 0; + public static final int CCBVAULTIC_AUTH_ID_MAX = 7; + + public static final int CCBVAULTIC_AUTH_ROLE_NONE = 0; + public static final int CCBVAULTIC_AUTH_ROLE_MANUFACTURER = 1; + public static final int CCBVAULTIC_AUTH_ROLE_UNAPPROVED = 2; + public static final int CCBVAULTIC_AUTH_ROLE_APPROVED = 3; + + public static final int CCBVAULTIC_AUTH_KIND_NONE = 0; + public static final int CCBVAULTIC_AUTH_KIND_PIN = 1; + public static final int CCBVAULTIC_AUTH_KIND_SCP03 = 2; + public static final int CCBVAULTIC_AUTH_KIND_KDF = 3; + + public static final int CCBVAULTIC_AUTH_PIN_LEN_MIN = 0x4; + public static final int CCBVAULTIC_AUTH_PIN_LEN_MAX = 0x20; + + public static final int CCBVAULTIC_AUTH_MAC_LEN = 0x10; /* AES128 keys only */ + public static final int CCBVAULTIC_AUTH_ENC_LEN = 0x10; /* AES128 keys only */ + + public static final int CCBVAULTIC_AUTH_KDF_KEY_LEN_MIN = 0x10; + public static final int CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX = 0x40; + public static final int CCBVAULTIC_AUTH_KDF_LABEL_LEN_MIN = 0x0; + public static final int CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX = 0x40; + + public static final int CCBVAULTIC_AUTH_ROLE_MANU = CCBVAULTIC_AUTH_ROLE_MANUFACTURER; + public static final int CCBVAULTIC_AUTH_ROLE_APP = CCBVAULTIC_AUTH_ROLE_UNAPPROVED; + public static final int CCBVAULTIC_AUTH_ROLE_DEBUG = CCBVAULTIC_AUTH_ROLE_UNAPPROVED; + + public static final int CCBVAULTIC_AUTH_ID_MANU = 7; + public static final int CCBVAULTIC_AUTH_ID_APP = 0; + public static final int CCBVAULTIC_AUTH_ID_DEBUG = 1; + + + public void SetByteBufferWithLen(ByteBuffer byteBuffer, long[] len, byte[] inData) + { + if ((byteBuffer == null) || (len == null)) { + return; + } + if((inData == null) || (inData.length == 0)) { + len[0] = 0; + return; + } + int minLen = Math.min(byteBuffer.limit(), inData.length); + byteBuffer.put(inData, 0 , minLen); + len[0] = minLen; + } + + public byte[] GetByteBufferWithLen(ByteBuffer byteBuffer, long[] len) + { + if ((byteBuffer == null) || (len == null) || (len[0] <= 0)) { + return null; + } + byte[] out = new byte[(int)len[0]]; + byteBuffer.get(out, 0, (int)len[0]); + return out; + } + + /* Buffer should be at least CCBVAULTIC_INFO_LEN bytes */ + public native int GetInfoText(int devId, ByteBuffer out, long[] outSz); + + public int GetInfoText(int devId, byte[] out) + { + ByteBuffer text = ByteBuffer.allocateDirect(CCBVAULTIC_INFO_LEN); + long[] text_len = {CCBVAULTIC_INFO_LEN}; + int rc = GetInfoText(devId, text, text_len); + + if (rc == 0) { + int minLen = Math.min((int)text_len[0], out.length); + text.get(out, 0, minLen); + } + return rc; + } + + public native int UpdateDefaultAuth(int id, int role, int kind, + ByteBuffer in1, long[] in1Sz, + ByteBuffer in2, long[] in2Sz); + + public int UpdateDefaultAuth_Pin(int id, int role, byte[] pin) + { + ByteBuffer pinBytes = ByteBuffer.allocateDirect(CCBVAULTIC_AUTH_PIN_LEN_MAX); + long[] pinLen = {0}; + SetByteBufferWithLen(pinBytes, pinLen, pin); + + return UpdateDefaultAuth(id, role, CCBVAULTIC_AUTH_KIND_PIN, + pinBytes, pinLen, + null, null); + } + + /* Role should be CCBVAULTIC_AUTH_ROLE_APPROVED or _UNAPPROVED */ + public int UpdateDefaultAuth_SCP03(int id, int role, byte[] mac, byte[] enc) + { + ByteBuffer macBytes = ByteBuffer.allocateDirect(CCBVAULTIC_AUTH_MAC_LEN); + long[] macLen = {0}; + + ByteBuffer encBytes = ByteBuffer.allocateDirect(CCBVAULTIC_AUTH_ENC_LEN); + long[] encLen = {0}; + + SetByteBufferWithLen(macBytes, macLen, mac); + SetByteBufferWithLen(encBytes, encLen, enc); + + return UpdateDefaultAuth(id, role, CCBVAULTIC_AUTH_KIND_SCP03, + macBytes, macLen, + encBytes, encLen); + } + + /* Role should be CCBVAULTIC_AUTH_ROLE_APPROVED or _UNAPPROVED */ + public int UpdateDefaultAuth_KDF(int id, int role, byte[] key, byte[] label) + { + ByteBuffer keyBytes = ByteBuffer.allocateDirect(CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX); + long[] keyLen = {0}; + + ByteBuffer labelBytes = ByteBuffer.allocateDirect(CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX); + long[] labelLen = {0}; + + SetByteBufferWithLen(keyBytes, keyLen, key); + SetByteBufferWithLen(labelBytes, labelLen, label); + + return UpdateDefaultAuth(id, role, CCBVAULTIC_AUTH_KIND_KDF, + keyBytes, keyLen, + labelBytes, labelLen); + } + + /* Manufacturer login */ + public int UpdateDefaultAuth_Manu(byte[] pin) + { + return UpdateDefaultAuth_Pin( + CCBVAULTIC_AUTH_ID_MANU, + CCBVAULTIC_AUTH_ROLE_MANU, + pin); + } + + /* App Login */ + public int UpdateDefaultAuth_App(byte[] key, byte[] label) + { + return UpdateDefaultAuth_KDF( + CCBVAULTIC_AUTH_ID_APP, + CCBVAULTIC_AUTH_ROLE_APP, + key, label); + } + + /* Debug login*/ + public int UpdateDefaultAuth_Debug(byte[] mac, byte[] enc) + { + return UpdateDefaultAuth_SCP03( + CCBVAULTIC_AUTH_ID_DEBUG, + CCBVAULTIC_AUTH_ROLE_DEBUG, + mac, enc); + } + + + public native int ProvisionAction(int devId, + boolean poweron_selftest, + int id, int role, int kind, //create user data + ByteBuffer userin1, long[] userin1Sz, + ByteBuffer userin2, long[] userin2Sz, + String inName1, ByteBuffer in1, long[] in1Sz, + String inName2, ByteBuffer in2, long[] in2Sz, + String inName3, ByteBuffer in3, long[] in3Sz); + public int ProvisionAction( int devId, + boolean poweron_selftest, + int id, int role, int kind, + byte[] userin1, byte[] userin2, + String inName1, byte[] in1, + String inName2, byte[] in2, + String inName3, byte[] in3 + ) + { + ByteBuffer userin1Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX); + long[] userin1Len = {0}; + ByteBuffer userin2Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX); + long[] userin2Len = {0}; + ByteBuffer in1Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_FILE_DATA_LEN_MAX); + long[] in1Len = {0}; + ByteBuffer in2Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_FILE_DATA_LEN_MAX); + long[] in2Len = {0}; + ByteBuffer in3Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_FILE_DATA_LEN_MAX); + long[] in3Len = {0}; + + SetByteBufferWithLen(userin1Bytes, userin1Len, userin1); + SetByteBufferWithLen(userin2Bytes, userin2Len, userin2); + SetByteBufferWithLen(in1Bytes, in1Len, in1); + SetByteBufferWithLen(in2Bytes, in2Len, in2); + SetByteBufferWithLen(in3Bytes, in3Len, in3); + + return ProvisionAction(devId, poweron_selftest, + id, role, + kind, userin1Bytes, userin1Len, userin2Bytes, userin2Len, + inName1, in1Bytes, in1Len, + inName2, in2Bytes, in2Len, + inName3, in3Bytes, in3Len); + } + + public int ProvisionAction_SCP03(int devId, + boolean poweron_selftest, + int id, int role, //create user data + byte[] mac, byte[] enc, + String inName1, byte[] in1, + String inName2, byte[] in2, + String inName3, byte[] in3) + { + if( (mac == null) || (mac.length != CCBVAULTIC_AUTH_MAC_LEN) || + (enc == null) || (enc.length != CCBVAULTIC_AUTH_ENC_LEN)) { + return -1; + } + return ProvisionAction(devId, poweron_selftest, + id, role, + CCBVAULTIC_AUTH_KIND_SCP03, mac, enc, + inName1, in1, + inName2, in2, + inName3, in3); + } + public int ProvisionAction_KDF(int devId, + boolean poweron_selftest, + int id, int role, //create user data + byte[] key, byte[] label, + String inName1, byte[] in1, + String inName2, byte[] in2, + String inName3, byte[] in3) + { + if( (key == null) || + (key.length < CCBVAULTIC_AUTH_KDF_KEY_LEN_MIN) || + (key.length > CCBVAULTIC_AUTH_KDF_KEY_LEN_MAX) || + (label == null) || + (label.length < CCBVAULTIC_AUTH_KDF_LABEL_LEN_MIN) || + (label.length > CCBVAULTIC_AUTH_KDF_LABEL_LEN_MAX)) { + return -1; + } + return ProvisionAction(devId, poweron_selftest, + id, role, + CCBVAULTIC_AUTH_KIND_KDF, key, label, + inName1, in1, + inName2, in2, + inName3, in3); + } + public int ProvisionAction_App(int devId, boolean poweron_selftest, + byte[] key, byte[] label, + String inName1, byte[] in1, + String inName2, byte[] in2, + String inName3, byte[] in3) + { + return ProvisionAction_KDF(devId, poweron_selftest, + CCBVAULTIC_AUTH_ID_APP, CCBVAULTIC_AUTH_ROLE_APP, + key, label,inName1, in1, inName2, in2, inName3, in3); + } + public int ProvisionAction_Debug(int devId, boolean poweron_selftest, + byte[] mac, byte[] enc, + String inName1, byte[] in1, + String inName2, byte[] in2, + String inName3, byte[] in3) + { + return ProvisionAction_SCP03(devId, poweron_selftest, + CCBVAULTIC_AUTH_ID_DEBUG, CCBVAULTIC_AUTH_ROLE_DEBUG, + mac, enc, inName1, in1, inName2, in2, inName3, in3); + } + + + /* Invoke the load action using the provided devId */ + public native int LoadAction(int devId, + String inName1, ByteBuffer out1Bytes, long[] out1Len, + String inName2, ByteBuffer out2Bytes, long[] out2Len, + String inName3, ByteBuffer out3Bytes, long[] out3Len); + + public class LoadFiles { + public int rc; + public byte[] file1; + public byte[] file2; + public byte[] file3; + } + public LoadFiles LoadAction(int devId, + String inName1, + String inName2, + String inName3) + { + ByteBuffer out1Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_FILE_DATA_LEN_MAX); + long[] out1Len = {CCBVAULTIC_FILE_DATA_LEN_MAX}; + ByteBuffer out2Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_FILE_DATA_LEN_MAX); + long[] out2Len = {CCBVAULTIC_FILE_DATA_LEN_MAX}; + ByteBuffer out3Bytes = ByteBuffer.allocateDirect(CCBVAULTIC_FILE_DATA_LEN_MAX); + long[] out3Len = {CCBVAULTIC_FILE_DATA_LEN_MAX}; + + LoadFiles out = new LoadFiles(); + out.rc= LoadAction(devId, + inName1, out1Bytes, out1Len, + inName2, out2Bytes, out2Len, + inName3, out3Bytes, out3Len); + if (out.rc == 0) { + out.file1 = GetByteBufferWithLen(out1Bytes,out1Len); + out.file2 = GetByteBufferWithLen(out2Bytes,out2Len); + out.file3 = GetByteBufferWithLen(out3Bytes,out3Len); + } + return out; + } + + + /* Copy data that is not a PEM header. Note this does not handle non-base64 text prior to the + * first header. */ + private byte[] StripPemHeaders(byte[] data) + { + if (data == null) return null; + /* Don't copy sections "-----xxxx-----" + * ^head + * ^desc + * ^foot + */ + int outSize = 0; + byte[] outData = new byte[data.length]; + boolean inHead = false; + boolean inDesc = false; + boolean inFoot = false; + + int dataoffset = 0; + // Search for "-----" and drop all data before then + for(dataoffset = 0; dataoffset < (data.length - 5); dataoffset ++) { + if( (data[dataoffset] == '-') && + (data[dataoffset + 1] == '-') && + (data[dataoffset + 2] == '-') && + (data[dataoffset + 3] == '-') && + (data[dataoffset + 4] == '-')) + break; + } + //Continue on removing comments + for (; dataoffset < data.length; dataoffset ++) { + byte datum = data[dataoffset]; + if (datum == '-') { + if (!inHead) { + inHead = true; + } else { + if (inDesc) { + inFoot = true; + } + } + // Always remove -'s + } else { + // Not a - + if (inFoot) { + //End of footer + inFoot = false; + inDesc = false; + inHead = false; + } else { + if (inHead) { + inDesc = true; + } + } + if (!inDesc) { + //Keep this byte + outData[outSize++] = datum; + } + } + } + //Truncate the output + return Arrays.copyOfRange(outData, 0, outSize); + } + public KeyManager[] GenerateKM(byte[] keyPem, byte[] crtPem) + { + /* Check for empty or missing files */ + if( (keyPem == null) || (keyPem.length == 0) || + (crtPem == null) || (crtPem.length == 0)) { + return null; + } + try { + byte[] keyFile = Base64.decode(StripPemHeaders(keyPem),Base64.DEFAULT); + byte[] crtFile = Base64.decode(StripPemHeaders(crtPem),Base64.DEFAULT); + + /* Parse the provided keyFile into a PrivateKey */ + KeyFactory kF = KeyFactory.getInstance("RSA"); + PrivateKey pK = kF.generatePrivate(new PKCS8EncodedKeySpec(keyFile)); + + /* Parse the provided crtFile into a X509Certificate[] CertChain */ + CertificateFactory cF = CertificateFactory.getInstance("X.509"); + Collection certs = + cF.generateCertificates(new ByteArrayInputStream(crtFile)); + X509Certificate[] certChain = new X509Certificate[certs.size()]; + int i=0; + for (Certificate cert:certs) { + certChain[i++] = (X509Certificate) cert; + } + + /* Create a PKCS12 KeyStore and put the PrivateKey and CertChain in */ + KeyStore kS = KeyStore.getInstance("PKCS12"); + kS.load(null, null); + kS.setKeyEntry("alias", pK, null, certChain); + + /* Create a KeyManagerFactory and Init it using the KeyStore */ + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(kS, null); + return kmf.getKeyManagers(); + } + catch (Exception e){ + /* Do something?*/ + } + return null; + } + + public TrustManager[] GenerateTM(byte[] cafile) + { + //TODO Process ca PEM file into a valid trust manager, similar to the KM above + return null; + } + + public native int PerformSelfTest(int devId); + +} diff --git a/ccb_vaultic/main-load.c b/ccb_vaultic/main-load.c new file mode 100644 index 000000000..3eaeedda1 --- /dev/null +++ b/ccb_vaultic/main-load.c @@ -0,0 +1,160 @@ +/* wolfCrypt load application for Wisekey VaultIC + * + * Copyright (C) 2023 wolfSSL Inc. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef WOLFSSL_USER_SETTINGS + #include "wolfssl/options.h" +#endif + +#include "wolfssl/ssl.h" + +#include "wolfssl/wolfcrypt/settings.h" /* For X-defines */ + +/* wolfCrypt includes */ +#include "wolfssl/wolfcrypt/wc_port.h" /* For Init/Cleanup */ + +#ifdef WOLF_CRYPTO_CB +#include "wolfssl/wolfcrypt/cryptocb.h" /* For Register/Unregister */ +#endif + +#ifdef HAVE_CCBVAULTIC +#include "ccb_vaultic.h" /* For devId and cryptocb */ +#endif + +/* Local include */ +#include "ccb_vaultic_config.h" /* For authentication and file data */ + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + int rc = 0; + + /* Initialize wolfSSL */ + rc = wolfSSL_Init(); + if (rc == WOLFSSL_SUCCESS) { + +#ifdef WOLF_CRYPTO_CB + /* Allocate/initialize context */ + void* c = NULL; + #if 1 + /* External allocation/initialization of hardware context */ + #ifdef HAVE_CCBVAULTIC + static ccbVaultIc_Context ctx_storage = CCBVAULTIC_CONTEXT_INITIALIZER; + c = &ctx_storage; + + ctx_storage.config = &gUserConfig; + rc = ccbVaultIc_Init(c); + #else + /* Add other elif hardware here */ + #endif + #endif /* WOLF_CRYPTO_CB_CMD */ + + if (rc == 0) { + /* Setup callback and devId */ + int devId = INVALID_DEVID; + CryptoDevCallbackFunc ccb = NULL; + #ifdef HAVE_CCBVAULTIC + devId = CCBVAULTIC420_DEVID; + ccb = ccbVaultIc_CryptoCb; + #else + /* Add other elif hardware here */ + #endif + + /* Register cryptocb */ + rc = wc_CryptoCb_RegisterDevice( + devId, + ccb, + c); +#endif /* WOLF_CRYPTO_CB */ + + if (rc == 0) { + /* Perform Load action */ + rc = ccbVaultIc_LoadAction(c, &gLoad); + + if (rc == 0) { + WOLFSSL_CTX* ctx = NULL; + int i; + for(i=0; i < gLoad.file_count; i++) { + printf("File %d: \n Name:%.*s\n Len:%d\n Data:%.*s\n---\n", + i, + gLoad.file[i].name_len, + gLoad.file[i].name, + gLoad.file[i].data_len, + gLoad.file[i].data_len, + gLoad.file[i].data + ); + } + ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method()); + if (ctx != NULL) { + rc = wolfSSL_CTX_use_PrivateKey_buffer( + ctx, + (const byte*)gLoad.file[0].data, + gLoad.file[0].data_len, + WOLFSSL_FILETYPE_PEM); + printf("Use PrivateKey with file %d returned %d\n",0,rc); + rc = wolfSSL_CTX_use_certificate_chain_buffer_format( + ctx, + (const byte*)gLoad.file[1].data, + gLoad.file[1].data_len, + WOLFSSL_FILETYPE_PEM); + printf("Use Certificate Chain with file %d returned %d\n",1,rc); + rc = wolfSSL_CTX_load_verify_chain_buffer_format( + ctx, + (const byte*)gLoad.file[2].data, + gLoad.file[2].data_len, + WOLFSSL_FILETYPE_PEM); + printf("Use Load Verify Chain with file %d returned %d\n",2,rc); + wolfSSL_CTX_free(ctx); + } + } + else + { + printf("Load failed with %d vlt_rc:%x\n", rc, ctx_storage.vlt_rc); + } + +#ifdef WOLF_CRYPTO_CB + /* Unregister the callback */ + wc_CryptoCb_UnRegisterDevice(devId); +#endif + } else { + printf("Failed to register cryptocb:%d (%x) "\ + " with devId:%x ccb:%p\n", + rc, rc, devId, ccb); + } + +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_CMD + /* External deallocation of hardware context */ + #ifdef HAVE_CCBVAULTIC + ccbVaultIc_Cleanup(c); + #else + /* Add other hardware cleanup here */ + #endif + #endif +#endif + } else { + printf(" Failed to initialize hardware: %d (%x)\n", rc, rc); + } + wolfSSL_Cleanup(); + }else { + printf("Failed to initialize wolfSSL: %d (%x)\n", rc, rc); + } + return rc; +} diff --git a/ccb_vaultic/main-prov.c b/ccb_vaultic/main-prov.c new file mode 100644 index 000000000..dca04cd4b --- /dev/null +++ b/ccb_vaultic/main-prov.c @@ -0,0 +1,124 @@ +/* wolfCrypt prov application for Wisekey VaultIC + * + * Copyright (C) 2023 wolfSSL Inc. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef WOLFSSL_USER_SETTINGS + #include "wolfssl/options.h" +#endif +#include "wolfssl/wolfcrypt/settings.h" /* For X-defines */ + +/* wolfCrypt includes */ +#include "wolfssl/wolfcrypt/wc_port.h" /* For Init/Cleanup */ + +#ifdef WOLF_CRYPTO_CB +#include "wolfssl/wolfcrypt/cryptocb.h" /* For Register/Unregister */ +#endif + +#ifdef HAVE_CCBVAULTIC +#include "ccb_vaultic.h" /* For devId and cryptocb */ +#endif + +/* Local include */ +#include "ccb_vaultic_config.h" /* For authentication and file data */ + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + int rc = 0; + + /* Initialize wolfCrypt */ + rc = wolfCrypt_Init(); + if (rc == 0) { + +#ifdef WOLF_CRYPTO_CB + /* Allocate/initialize context */ + void* ctx = NULL; + #if 1 + /* External allocation/initialization of hardware context */ + #ifdef HAVE_CCBVAULTIC + static ccbVaultIc_Context ctx_storage = CCBVAULTIC_CONTEXT_INITIALIZER; + ctx = &ctx_storage; + + ctx_storage.config = &gManuConfig; + rc = ccbVaultIc_Init(ctx); + #else + /* Add other elif hardware here */ + #endif + #endif /* WOLF_CRYPTO_CB_CMD */ + + if (rc == 0) { + /* Setup callback and devId */ + int devId = INVALID_DEVID; + CryptoDevCallbackFunc ccb = NULL; + #ifdef HAVE_CCBVAULTIC + devId = CCBVAULTIC420_DEVID; + ccb = ccbVaultIc_CryptoCb; + #else + /* Add other elif hardware here */ + #endif + + /* Register cryptocb */ + rc = wc_CryptoCb_RegisterDevice( + devId, + ccb, + ctx); +#endif /* WOLF_CRYPTO_CB */ + + if (rc == 0) { + /* Perform Load action */ + rc = ccbVaultIc_ProvisionAction(ctx, &gProvision); + + if (rc == 0) { + printf("Provision succeeded.\n"); + } + else + { + printf("Provision failed with %d vlt_rc:%x\n", rc, ctx_storage.vlt_rc); + } + +#ifdef WOLF_CRYPTO_CB + /* Unregister the callback */ + wc_CryptoCb_UnRegisterDevice(devId); +#endif + } else { + printf("Failed to register cryptocb:%d (%x) "\ + " with devId:%x ccb:%p\n", + rc, rc, devId, ccb); + } + +#ifdef WOLF_CRYPTO_CB + #ifndef WOLF_CRYPTO_CB_CMD + /* External deallocation of hardware context */ + #ifdef HAVE_CCBVAULTIC + ccbVaultIc_Cleanup(ctx); + #else + /* Add other hardware cleanup here */ + #endif + #endif +#endif + } else { + printf(" Failed to initialize hardware: %d (%x)\n", rc, rc); + } + wolfCrypt_Cleanup(); + }else { + printf("Failed to initialize wolfCrypt: %d (%x)\n", rc, rc); + } + return rc; +}