/* * Validate the signature over a PCR composite structure. * Returns '0' on success, an error code otherwise. */ uint32_t TPM_ValidatePCRCompositeSignature(TPM_PCR_COMPOSITE *tpc, unsigned char *antiReplay, pubkeydata *pk, struct tpm_buffer *signature, uint16_t sigscheme) { uint32_t ret; RSA *rsa; /* openssl RSA public key */ TPM_QUOTE_INFO tqi; STACK_TPM_BUFFER (ser_tqi); STACK_TPM_BUFFER(response); STACK_TPM_BUFFER (ser_tpc); /* ** Convert to an OpenSSL RSA public key */ rsa = TSS_convpubkey(pk); ret = TPM_GetCapability(TPM_CAP_VERSION, NULL, &response); if (ret != 0) { RSA_free(rsa); return ret; } memcpy(&(tqi.version), response.buffer, response.used); memcpy(&(tqi.fixed), "QUOT", 4); memcpy(&(tqi.externalData), antiReplay, TPM_NONCE_SIZE); ret = TPM_WritePCRComposite(&ser_tpc, tpc); if ((ret & ERR_MASK)) { RSA_free(rsa); return ret; } /* create the hash of the PCR_composite data for the quoteinfo structure */ TSS_sha1(ser_tpc.buffer, ser_tpc.used, tqi.digestValue); ret = TPM_WriteQuoteInfo(&ser_tqi, &tqi); if ((ret & ERR_MASK)) { RSA_free(rsa); return ret; } ret = TPM_ValidateSignature(sigscheme, &ser_tqi, signature, rsa); RSA_free(rsa); return ret; }
int main(int argc, char *argv[]) { uint32_t ret; STACK_TPM_BUFFER(resp); int index = 0; STACK_TPM_BUFFER( subcap );; TPM_setlog(0); /* turn off verbose output */ ParseArgs(argc, argv); while ((int)matrx[index].cap != -1) { if (cap == matrx[index].cap) { break; } index++; } if (-1 == (int)matrx[index].cap) { printf("Unknown or unsupported capability!\n"); exit(-1); } subcap.used = 0; if (matrx[index].subcap_size > 0) { if ((int)scap == -1) { printf("Need subcap parameter for this capability!\n"); exit(-1); } if (0 == prepare_subcap(cap, &subcap, scap)) { if (2 == matrx[index].subcap_size) { STORE16(subcap.buffer,0,scap); subcap.used = 2; } else if (matrx[index].subcap_size >= 4) { STORE32(subcap.buffer,0,scap); subcap.used = 4; } } } #if 0 /* This was for VTPM extensions and needs retest */ if (cap == TPM_CAP_MFR) { int idx2 = 0; while ((int)mfr_matrix[idx2].cap != -1) { if (mfr_matrix[idx2].cap == scap) { break; } idx2++; } if (mfr_matrix[idx2].subcap_size > 0) { uint32_t used = subcap.used + mfr_matrix[idx2].subcap_size; while (subcap.used < used) { if (argc <= nxtarg) { printf("Need one more parameter for this " "capability!\n"); exit(-1); } if (!strncmp("0x",argv[nxtarg],2)) { sscanf(argv[nxtarg],"%x",&sscap); } else { sscanf(argv[nxtarg],"%d",&sscap); } nxtarg++; if (2 == matrx[index].subcap_size) { STORE16(subcap.buffer, subcap.used,sscap); subcap.used += 2; } else if (matrx[index].subcap_size >= 4) { STORE32(subcap.buffer, subcap.used,sscap); subcap.used += 4; } } } } #endif if (0 == sikeyhandle) { ret = TPM_GetCapability(cap, &subcap, &resp); if (0 != ret) { printf("TPM_GetCapability returned %s.\n", TPM_GetErrMsg(ret)); exit(ret); } } else { unsigned char antiReplay[TPM_HASH_SIZE]; unsigned char signature[2048]; uint32_t signaturelen = sizeof(signature); pubkeydata pubkey; RSA * rsa; unsigned char sighash[TPM_HASH_SIZE]; unsigned char * buffer = NULL; unsigned char * sigkeyhashptr = NULL; unsigned char sigkeypasshash[TPM_HASH_SIZE]; if (NULL != sikeypass) { TSS_sha1(sikeypass,strlen(sikeypass),sigkeypasshash); sigkeyhashptr = sigkeypasshash; } TSS_gennonce(antiReplay); ret = TPM_GetPubKey(sikeyhandle, sigkeyhashptr, &pubkey); if (0 != ret) { printf("Error while trying to access the signing key's public key.\n"); exit(-1); } rsa = TSS_convpubkey(&pubkey); ret = TPM_GetCapabilitySigned(sikeyhandle, sigkeyhashptr, antiReplay, cap, &subcap, &resp, signature, &signaturelen); if (0 != ret) { printf("TPM_GetCapabilitySigned returned %s.\n", TPM_GetErrMsg(ret)); exit(ret); } buffer = malloc(resp.used+TPM_NONCE_SIZE); if (NULL == buffer) { printf("Could not allocate buffer.\n"); exit(-1); } memcpy(&buffer[0], resp.buffer, resp.used); memcpy(&buffer[resp.used], antiReplay, TPM_NONCE_SIZE); TSS_sha1(buffer, resp.used+TPM_NONCE_SIZE, sighash); free(buffer); ret = RSA_verify(NID_sha1, sighash,TPM_HASH_SIZE, signature,signaturelen, rsa); if (1 != ret) { printf("Error: Signature verification failed.\n"); exit(-1); } } if (0 == resp.used) { printf("Empty response.\n"); } else { if (-1 == (int)scap) { printf("Result for capability 0x%x is : ",cap); } else { printf("Result for capability 0x%x, subcapability 0x%x is : ",cap,scap); } if (TYPE_BOOL == matrx[index].result_size) { if (resp.buffer[0] == 0) { printf("FALSE\n"); } else { printf("TRUE\n"); } } else if (TYPE_UINT32 == matrx[index].result_size) { uint32_t rsp; rsp = LOAD32(resp.buffer,0); printf("0x%08X = %d\n",rsp,rsp); } else if (TYPE_UINT32_ARRAY == matrx[index].result_size) { int i = 0; printf("\n"); while (i+3 < (int)resp.used) { uint32_t rsp = LOAD32(resp.buffer,i); i+=4; if (TPM_CAP_NV_LIST == cap) { /* don't zero extend, grep needs the exact value for test suite */ printf("%d. Index : %d = 0x%x.\n", i/4, rsp, rsp); } else if (TPM_CAP_KEY_HANDLE == cap) { printf("%d. keyhandle : %d.\n", i/4, rsp); } else { printf("%d. item : %d.\n", i/4, rsp); } } } else if (TYPE_STRUCTURE == matrx[index].result_size) { switch(cap) { case TPM_CAP_FLAG: { if (scap == TPM_CAP_FLAG_PERMANENT) { TPM_PERMANENT_FLAGS pf; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadPermanentFlags(&tb, 0, &pf, resp.used); if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showPermanentFlags(&pf, resp.used); } else if (scap == TPM_CAP_FLAG_VOLATILE) { TPM_STCLEAR_FLAGS sf; STACK_TPM_BUFFER(tb); TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadSTClearFlags(&tb, 0, &sf); if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showVolatileFlags(&sf); } } break; case TPM_CAP_KEY_HANDLE: { uint16_t num = LOAD16(resp.buffer, 0); uint32_t i = 0; uint32_t handle; printf("\n"); while (i < num) { handle = LOAD32(resp.buffer,2+i*4); printf("%d. handle: 0x%08X\n", i, handle); i++; } } break; case TPM_CAP_NV_INDEX: { //char scratch_info[256]; unsigned char scratch_info[256]; uint32_t scratch_info_len; TPM_NV_DATA_PUBLIC ndp; uint32_t i, c; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadNVDataPublic(&tb, 0, &ndp); if ( ( ret & ERR_MASK) != 0) { printf("Could not deserialize the TPM_NV_DATA_PUBLIC structure.\n"); exit(-1); } printf("permission.attributes : %08X\n",(unsigned int)ndp.permission.attributes); printf("ReadSTClear : %02X\n",ndp.bReadSTClear); printf("WriteSTClear : %02X\n",ndp.bWriteSTClear); printf("WriteDefine : %02X\n",ndp.bWriteDefine); printf("dataSize : %08X = %d",(unsigned int)ndp.dataSize, (unsigned int)ndp.dataSize); c = 0; for (i = 0; i < ndp.pcrInfoRead.pcrSelection.sizeOfSelect*8; i++) { if (ndp.pcrInfoRead.pcrSelection.pcrSelect[(i / 8)] & (1 << (i & 0x7))) { if (!c) printf("\nRead PCRs selected: "); else printf(", "); printf("%d", i); c++; } } if (c) { char pcrmap[4], *pf; memcpy(pcrmap, ndp.pcrInfoRead.pcrSelection.pcrSelect, ndp.pcrInfoRead.pcrSelection.sizeOfSelect); // printf("\npcrmap: %02x%02x%02x%02x\n", pcrmap[0], pcrmap[1], // pcrmap[2], pcrmap[3]); ret = TSS_GenPCRInfo(*(uint32_t *)pcrmap, scratch_info, &scratch_info_len); printf("\nRead PCR Composite: "); for (i = 0; i < 20; i++) printf("%02x", ndp.pcrInfoRead.digestAtRelease[i] & 0xff); printf("\n"); #if 1 pf = &scratch_info[5]; printf("\nCurrent PCR composite: "); for (i = 0; i < 20; i++) //printf("%02x", scratch_info.digestAtRelease[i] & 0xff); printf("%02x", pf[i] & 0xff); printf("\n"); #endif if (!ret) { printf("Matches current TPM state: "); if (!memcmp(&scratch_info[5], &ndp.pcrInfoRead.digestAtRelease, 20)) { printf("Yes\n"); } else { printf("No\n"); } } } c = 0; for (i = 0; i < ndp.pcrInfoWrite.pcrSelection.sizeOfSelect*8; i++) { if (ndp.pcrInfoWrite.pcrSelection.pcrSelect[(i / 8)] & (1 << (i & 0x7))) { if (!c) printf("\nWrite PCRs selected: "); else printf(", "); printf("%d", i); c++; } } if (c) { printf("\nWrite PCR Composite: "); for (i = 0; i < 20; i++) printf("%02x", ndp.pcrInfoWrite.digestAtRelease[i] & 0xff); printf("\n"); } } break; case TPM_CAP_HANDLE: { uint16_t num = LOAD16(resp.buffer, 0); uint16_t x = 0; while (x < num) { uint32_t handle = LOAD32(resp.buffer, sizeof(num)+4*x); printf("%02d. 0x%08X\n",x,handle); x++; } } break; case TPM_CAP_VERSION_VAL: { int i = 0; TPM_CAP_VERSION_INFO cvi; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadCapVersionInfo(&tb, 0, &cvi); if ( ( ret & ERR_MASK) != 0) { printf("Could not read the version info structure.\n"); exit(-1); } printf("\n"); printf("major : 0x%02X\n",cvi.version.major); printf("minor : 0x%02X\n",cvi.version.minor); printf("revMajor : 0x%02X\n",cvi.version.revMajor); printf("revMinor : 0x%02X\n",cvi.version.revMinor); printf("specLevel : 0x%04X\n",cvi.specLevel); printf("errataRev : 0x%02X\n",cvi.errataRev); printf("VendorID : "); while (i < 4) { printf("%02X ",cvi.tpmVendorID[i]); i++; } printf("\n"); /* Print vendor ID in text if printable */ for (i=0 ; i<4 ; i++) { if (isprint(cvi.tpmVendorID[i])) { if (i == 0) { printf("VendorID : "); } printf("%c", cvi.tpmVendorID[i]); } else { break; } } printf("\n"); printf("[not displaying vendor specific information]\n"); } break; #if 0 /* kgold: I don't think these are valid cap values */ case TPM_CAP_FLAG_PERMANENT: { TPM_PERMANENT_FLAGS pf; STACK_TPM_BUFFER(tb) TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); if (resp.used == 21) { ret = TPM_ReadPermanentFlagsPre103(&tb, 0, &pf); } else { ret = TPM_ReadPermanentFlags(&tb, 0, &pf); } if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showPermanentFlags(&pf, resp.used); } break; case TPM_CAP_FLAG_VOLATILE: { TPM_STCLEAR_FLAGS sf; STACK_TPM_BUFFER(tb); TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadSTClearFlags(&tb, 0, &sf); if ( ( ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } printf("\n"); showVolatileFlags(&sf); } break; #endif case TPM_CAP_DA_LOGIC: { uint32_t ctr; TPM_BOOL lim = FALSE; TPM_DA_INFO dainfo; TPM_DA_INFO_LIMITED dainfo_lim; STACK_TPM_BUFFER(tb); TSS_SetTPMBuffer(&tb, resp.buffer, resp.used); ret = TPM_ReadDAInfo(&tb, 0, &dainfo); if ( ( ret & ERR_MASK) != 0 || ret > resp.used) { ret = TPM_ReadDAInfoLimited(&tb, 0, &dainfo_lim); if ( (ret & ERR_MASK ) != 0 || ret > resp.used) { printf("ret=%x, responselen=%d\n",ret,resp.used); printf("Error parsing response!\n"); exit(-1); } else { lim = TRUE; } } printf("\n"); if (lim) { printf("State : %d\n",dainfo_lim.state); printf("Actions : 0x%08x\n",dainfo_lim.actionAtThreshold.actions); ctr = 0; while (ctr < dainfo_lim.vendorData.size) { printf("%02x ",(unsigned char)dainfo_lim.vendorData.buffer[ctr]); ctr++; } } else { printf("State : %d\n",dainfo.state); printf("currentCount : %d\n",dainfo.currentCount); printf("thresholdCount : %d\n",dainfo.thresholdCount); printf("Actions : 0x%08x\n",dainfo.actionAtThreshold.actions); printf("actionDependValue : %d\n",dainfo.actionDependValue); #if 0 ctr = 0; while (ctr < dainfo_lim.vendorData.size) { printf("%02x ",(unsigned char)dainfo_lim.vendorData.buffer[ctr]); ctr++; } #endif } } break; } } else if (TYPE_VARIOUS == matrx[index].result_size) { switch(cap) { case TPM_CAP_MFR: switch (scap) { case TPM_CAP_PROCESS_ID: { uint32_t rsp; rsp = LOAD32(resp.buffer,0); printf("%d\n",rsp); } break; } break; /* TPM_CAP_MFR */ default: /* Show booleans */ if (scap == TPM_CAP_PROP_OWNER || scap == TPM_CAP_PROP_DAA_INTERRUPT ) { if (0 == resp.buffer[0]) { printf("FALSE\n"); } else { printf("TRUE\n"); } } else /* check for array of 4 UINTs */ if (scap == TPM_CAP_PROP_TIS_TIMEOUT /* || scap == TPM_CAP_PROP_TIMEOUTS */) { int i = 0; while (i < 4) { uint32_t val = LOAD32(resp.buffer,i * 4); printf("%d ", val); i++; } printf("\n"); } else /* check for TPM_STARTUP_EFFECTS */ if (scap == TPM_CAP_PROP_STARTUP_EFFECT) { TPM_STARTUP_EFFECTS se = 0; ret = TPM_ReadStartupEffects(resp.buffer, &se); if ( ( ret & ERR_MASK ) != 0 ) { printf("Could not read startup effects structure.\n"); exit(-1); } printf("0x%08X=%d\n", (unsigned int)se, (unsigned int)se); printf("\n"); printf("Startup effects:\n"); printf("Effect on audit digest: %s\n", (se & (1 << 7)) ? "none" : "active"); printf("Audit Digest on TPM_Startup(ST_CLEAR): %s\n", ( se & (1 << 6)) ? "set to NULL" : "not set to NULL" ); printf("Audit Digest on TPM_Startup(any) : %s\n", ( se & (1 << 5)) ? "set to NULL" : "not set to NULL" ); printf("TPM_RT_KEY resource initialized on TPM_Startup(ST_ANY) : %s\n", (se & ( 1 << 4)) ? "yes" : "no"); printf("TPM_RT_AUTH resource initialized on TPM_Startup(ST_STATE) : %s\n", (se & ( 1 << 3)) ? "yes" : "no"); printf("TPM_RT_HASH resource initialized on TPM_Startup(ST_STATE) : %s\n", (se & ( 1 << 2)) ? "yes" : "no"); printf("TPM_RT_TRANS resource initialized on TPM_Startup(ST_STATE) : %s\n", (se & ( 1 << 1)) ? "yes" : "no"); printf("TPM_RT_CONTEXT session initialized on TPM_Startup(ST_STATE): %s\n", (se & ( 1 << 0)) ? "yes" : "no"); } else /* check for array of 3 UINTs */ if (scap == TPM_CAP_PROP_DURATION) { int i = 0; while (i < 4*3) { uint32_t val = LOAD32(resp.buffer,i); printf("%d ", val); i+= 4; } printf("\n"); } else /* check for TPM_COUNT_ID */ if (scap == TPM_CAP_PROP_ACTIVE_COUNTER) { uint32_t val = LOAD32(resp.buffer,0); printf("0x%08X=%d",val,val); if (0xffffffff == val) { printf(" (no counter is active)"); } printf("\n"); } else { /* just a single UINT32 */ printf("%ld=0x%08lX.\n", (long)LOAD32(resp.buffer, 0), (long)LOAD32(resp.buffer, 0)); } } } } printf("\n"); exit(0); }
int main(int argc, char **argv) { int fd, size, i, ret; uint32_t kh, pcrs; unsigned char buf[1024], hash[20], pass[20]; char *srkpass, *keyfile, ch; /* SHA1 hash of TPM's SRK password */ char *tpmhash = "\x71\x10\xed\xa4\xd0\x9e\x06\x2a\xa5\xe4\xa3" "\x90\xb0\xa5\x72\xac\x0d\x2c\x02\x20"; char *nonce = "\x80\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0" "\x0\x0\x0\x0\x1"; keydata k; RSA *rpub; srkpass = keyfile = NULL; while ((ch = getopt(argc, argv, "hs:f:")) != -1) { switch (ch) { case 's': srkpass = optarg; break; case 'f': keyfile = optarg; break; case 'h': default: usage(argv[0]); break; } } if (!srkpass) usage(argv[0]); if (!keyfile) keyfile = "key.blob"; SHA1(srkpass, strlen(srkpass), pass); fd = open(keyfile, O_RDONLY); if (fd == -1) errx(1, "couldn't open %s\n", keyfile); size = read(fd, buf, 1024); if (size == -1) errx(1, "couldn't read\n"); size = TSS_KeyExtract(buf, &k); printf("keybuf size: %d\n", size); close(fd); printf("loading . . .\n"); /* 0x40000000 is the UID for the SRK */ if (ret = TPM_LoadKey(0x40000000, pass, &k, &kh)) { printf("%s\n", TPM_GetErrMsg(ret)); errx(1, "TPM_LoadKey\n"); } /* Quote PCR 0 */ printf("quoting . . .\n"); if (ret = TPM_Quote(kh, (0x00000001 << 0), pass, nonce, &pcomp, buf, &size)) { printf("%s\n", TPM_GetErrMsg(ret)); errx(1, "TPM_Quote\n"); } /* TPM will run out of memory if you forget to evict keys. This can be * fixed with a good ol' reboot.*/ printf("evicting. . .\n"); if (ret = TPM_EvictKey(kh)) { printf("%s\n", TPM_GetErrMsg(ret)); errx(1, "TPM_EvictKey\n"); } /* Compute composite hash */ SHA1((char*)&pcomp, sizeof(pcomp), hash); printf("slen: %d\n", ntohs(pcomp.slen)); printf("select: 0x%x\n", pcomp.s); printf("plen %d\n", ntohl(pcomp.plen)); printf("pcr hash: "); for (i = 0; i < 20; i++) printf("%02x ", pcomp.p[i]); printf("\n"); printf("composite hash: "); for (i = 0; i < 20; i++) printf("%02x ", hash[i]); printf("\n"); printf("signed blob len: %d\n", size); printf("signed blob: "); for (i = 0; i < size; i++) printf("%02x ", buf[i]); printf("\n"); /* See if the signed object matches the composite hash concatenated * with the nonce */ signedhash.fixed[0] = 1; signedhash.fixed[1] = 1; signedhash.fixed[2] = 0; signedhash.fixed[3] = 0; signedhash.fixed[4] = 'Q'; signedhash.fixed[5] = 'U'; signedhash.fixed[6] = 'O'; signedhash.fixed[7] = 'T'; memcpy(&signedhash.comphash, hash, 20); memcpy(&signedhash.nonce, nonce, 20); SHA1((char*)&signedhash, sizeof(signedhash), hash); /* Gives us an RSA public key from the TPM key */ rpub = TSS_convpubkey(&k.pub); if (!rpub) errx(1, "TSS_convpubkey\n"); if (!RSA_verify(NID_sha1, hash, 20, buf, size, rpub)) printf("SIGNATURE FAILED\n"); else printf("Signature is correct\n"); return 0; }
int main(int argc, char *argv[]) { uint32_t startOrdinal = -1; int ret; int verbose = FALSE; TPM_COUNTER_VALUE counter; int i = 1; char * keypass = NULL; unsigned char keyAuth[TPM_HASH_SIZE]; unsigned char * keyAuthPtr = NULL; uint32_t keyhandle = -1; STACK_TPM_BUFFER(signature); unsigned char digest[TPM_DIGEST_SIZE]; unsigned char ordinalDigest[TPM_DIGEST_SIZE]; unsigned char antiReplay[TPM_NONCE_SIZE]; TPM_setlog(0); TSS_gennonce(antiReplay); while (i < argc) { if (!strcmp("-s",argv[i])) { i++; if (i < argc) { sscanf(argv[i],"%d",&startOrdinal); } else { printf("Missing parameter for -s.\n"); usage(); } } else if (!strcmp("-h",argv[i])) { i++; if (i < argc) { sscanf(argv[i],"%x",&keyhandle); } else { printf("Missing parameter for -h.\n"); usage(); } } else if (!strcmp("-p",argv[i])) { i++; if (i < argc) { keypass = argv[i]; } else { printf("Missing parameter for -p.\n"); usage(); } } else if (!strcmp("-v",argv[i])) { verbose = TRUE; TPM_setlog(1); } else { printf("\n%s is not a valid option\n", argv[i]); usage(); } i++; } (void)verbose; if (-1 == (int)startOrdinal || -1 == (int)keyhandle) { printf("Missing command line parameter.\n"); usage(); } if (NULL != keypass) { TSS_sha1(keypass,strlen(keypass),keyAuth); keyAuthPtr = keyAuth; } ret = TPM_GetAuditDigestSigned(keyhandle, FALSE, keyAuthPtr, antiReplay, &counter, digest, ordinalDigest, &signature); if (0 != ret) { printf("Error %s from GetAuditDigestSigned.\n", TPM_GetErrMsg(ret)); } else { TPM_SIGN_INFO tsi; STACK_TPM_BUFFER(tsi_ser); STACK_TPM_BUFFER(serial); STACK_TPM_BUFFER(ctr_ser); pubkeydata pubkey; RSA *rsa; i = 0; printf("AuditDigest : "); while (i < (int)sizeof(digest)) { printf("%02X",digest[i]); i++; } printf("\n"); i = 0; printf("OrdinalDigest : "); while (i < (int)sizeof(digest)) { printf("%02X",ordinalDigest[i]); i++; } printf("\n"); ret = TPM_GetPubKey(keyhandle, keyAuthPtr, &pubkey); if (ret != 0) { printf("Could not get public key of signing key.\n"); exit(-1); } rsa = TSS_convpubkey(&pubkey); if (!rsa) { printf("Could not convert public key.\n"); exit(-1); } tsi.tag = TPM_TAG_SIGNINFO; memcpy(tsi.fixed, "ADIG", 4); memcpy(tsi.replay, antiReplay, sizeof(antiReplay)); /* D4=ordinalDigest */ TPM_WriteCounterValue(&ctr_ser, &counter); memcpy(&serial.buffer[0], digest, sizeof(digest)); memcpy(&serial.buffer[sizeof(digest)], ctr_ser.buffer, ctr_ser.used); memcpy(&serial.buffer[sizeof(digest)+ctr_ser.used], ordinalDigest, sizeof(ordinalDigest)); serial.used = sizeof(digest) + ctr_ser.used + sizeof(ordinalDigest); tsi.data.size = serial.used; tsi.data.buffer = serial.buffer; ret = TPM_WriteSignInfo(&tsi_ser, &tsi); if ((ret & ERR_MASK)) { printf("Error serializing TPM_SIGN_INFO.\n"); exit(-1); } ret = TPM_ValidateSignature(TPM_SS_RSASSAPKCS1v15_SHA1, &tsi_ser, &signature, rsa); if (ret != 0) { printf("Error validating signature.\n"); exit(-1); } printf("Signature verification successful.\n"); } exit(ret); }
int main(int argc, char *argv[]) { int ret; /* general return value */ uint32_t keyhandle = 0; /* handle of quote key */ unsigned int pcrmask = 0; /* pcr register mask */ unsigned char passhash1[TPM_HASH_SIZE]; /* hash of key password */ unsigned char data[TPM_HASH_SIZE];/* nonce data */ STACK_TPM_BUFFER(signature); pubkeydata pubkey; /* public key structure */ RSA *rsa; /* openssl RSA public key */ unsigned char *passptr; TPM_PCR_SELECTION selection; TPM_PCR_INFO_SHORT s1; TPM_QUOTE_INFO2 quoteinfo; STACK_TPM_BUFFER( serQuoteInfo ) uint32_t pcrs; int i; uint16_t sigscheme = TPM_SS_RSASSAPKCS1v15_SHA1; TPM_BOOL addVersion = FALSE; STACK_TPM_BUFFER(versionblob); static char *keypass = NULL; TPM_setlog(0); /* turn off verbose output from TPM driver */ for (i=1 ; i<argc ; i++) { if (strcmp(argv[i],"-hk") == 0) { i++; if (i < argc) { /* convert key handle from hex */ if (1 != sscanf(argv[i], "%x", &keyhandle)) { printf("Invalid -hk argument '%s'\n",argv[i]); exit(2); } } else { printf("-hk option needs a value\n"); printUsage(); } } else if (!strcmp(argv[i], "-pwdk")) { i++; if (i < argc) { keypass = argv[i]; } else { printf("Missing parameter to -pwdk\n"); printUsage(); } } else if (strcmp(argv[i],"-bm") == 0) { i++; if (i < argc) { /* convert key handle from hex */ if (1 != sscanf(argv[i], "%x", &pcrmask)) { printf("Invalid -bm argument '%s'\n",argv[i]); exit(2); } } else { printf("-bm option needs a value\n"); printUsage(); } } else if (!strcmp(argv[i], "-vinfo")) { addVersion = TRUE; printf("Adding version info.\n"); } else if (!strcmp(argv[i], "-h")) { printUsage(); } else if (!strcmp(argv[i], "-v")) { TPM_setlog(1); } else { printf("\n%s is not a valid option\n", argv[i]); printUsage(); } } if ((keyhandle == 0) || (pcrmask == 0)) { printf("Missing argument\n"); printUsage(); } memset(&s1, 0x0, sizeof(s1)); /* ** Parse and process the command line arguments */ /* get the SHA1 hash of the password string for use as the Key Authorization Data */ if (keypass != NULL) { TSS_sha1((unsigned char *)keypass,strlen(keypass),passhash1); passptr = passhash1; } else { passptr = NULL; } /* for testing, use the password hash as the test nonce */ memcpy(data,passhash1,TPM_HASH_SIZE); ret = TPM_GetNumPCRRegisters(&pcrs); if (ret != 0) { printf("Error reading number of PCR registers.\n"); exit(-1); } if (pcrs > TPM_NUM_PCR) { printf("Library does not support that many PCRs.\n"); exit(-1); } memset(&selection, 0x0, sizeof(selection)); selection.sizeOfSelect = pcrs / 8; for (i = 0; i < selection.sizeOfSelect; i++) { selection.pcrSelect[i] = (pcrmask & 0xff); pcrmask >>= 8; } /* ** perform the TPM Quote function */ ret = TPM_Quote2(keyhandle, /* key handle */ &selection, /* specify PCR registers */ addVersion, /* add Version */ passptr, /* Key Password (hashed), or null */ data, /* nonce data */ &s1, /* pointer to pcr info */ &versionblob, /* pointer to TPM_CAP_VERSION_INFO */ &signature); /* buffer to receive result, int to receive result length */ if (ret != 0) { printf("Error '%s' from TPM_Quote2\n",TPM_GetErrMsg(ret)); exit(ret); } /* ** Get the public key and convert to an OpenSSL RSA public key */ ret = TPM_GetPubKey(keyhandle,passptr,&pubkey); if (ret != 0) { printf("Error '%s' from TPM_GetPubKey\n",TPM_GetErrMsg(ret)); exit(ret); } rsa = TSS_convpubkey(&pubkey); /* ** fill the quote info structure and calculate the hashes needed for verification */ quoteinfo.tag = TPM_TAG_QUOTE_INFO2; memcpy(&(quoteinfo.fixed),"QUT2",4); quoteinfo.infoShort = s1; memcpy(&(quoteinfo.externalData),data,TPM_NONCE_SIZE); unsigned char *corey_ptr = (unsigned char *)"einfo; unsigned int x; printf("quote info: \n"); for (x=0;x<128;x++) { if (x != 0 && x % 16 == 0) printf("\n"); printf("%02x ", corey_ptr[x]); } printf("\n"); /* create the hash of the quoteinfo structure for signature verification */ ret = TPM_WriteQuoteInfo2(&serQuoteInfo, "einfo); if ( ( ret & ERR_MASK ) != 0) { exit(-1); } printf("serquoteinfo: \n"); for (x=0;x<128;x++) { if (x != 0 && x % 16 == 0) printf("\n"); printf("%02x ", serQuoteInfo.buffer[x]); } printf("\n"); /* append version information if given in response */ if (addVersion) { printf("addversion is called\n"); memcpy(serQuoteInfo.buffer + serQuoteInfo.used, versionblob.buffer, versionblob.used); serQuoteInfo.used += versionblob.used; } ret = TPM_ValidateSignature(sigscheme, &serQuoteInfo, &signature, rsa); if (ret != 0) { printf("Verification failed\n"); } else { printf("Verification succeeded\n"); } RSA_free(rsa); exit(ret); }
uint32_t TPM_TakeOwnership(unsigned char *ownpass, unsigned char *srkpass, keydata * key) { unsigned char take_owner_fmt[] = "00 c2 T l s @ @ % l % 00 %"; /* required OAEP padding P parameter */ unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; uint32_t ret; int iret; unsigned char tpmdata[TPM_MAX_BUFF_SIZE]; pubkeydata tpmpubkey; /* public endorsement key data */ uint32_t srkparamsize; /* SRK parameter buffer size */ unsigned char nonceeven[TPM_HASH_SIZE]; /* even nonce (from OIAPopen) */ RSA *pubkey; /* PubEK converted to OpenSSL format */ unsigned char padded[RSA_MODULUS_BYTE_SIZE]; keydata srk; /* key info for SRK */ unsigned char dummypass[TPM_HASH_SIZE]; /* dummy srk password */ unsigned char *spass; /* pointer to srkpass or dummy */ unsigned int i; /* data to be inserted into Take Owner Request Buffer */ /* the uint32_t and uint16_t values are stored in network byte order */ uint32_t command; /* command ordinal */ uint16_t protocol; /* protocol ID */ uint32_t oencdatasize; /* owner auth data encrypted size */ unsigned char ownerencr[RSA_MODULUS_BYTE_SIZE]; uint32_t sencdatasize; /* srk auth data encrypted size */ unsigned char srkencr[RSA_MODULUS_BYTE_SIZE]; unsigned char srk_param_buff[TPM_SRK_PARAM_BUFF_SIZE]; uint32_t authhandle; /* auth handle (from OIAPopen) */ unsigned char nonceodd[TPM_HASH_SIZE]; /* odd nonce */ unsigned char authdata[TPM_HASH_SIZE]; /* auth data */ /* check that parameters are valid */ if (ownpass == NULL) return ERR_NULL_ARG; if (srkpass == NULL) { memset(dummypass, 0, sizeof dummypass); spass = dummypass; } else spass = srkpass; /* set up command and protocol values for TakeOwnership function */ command = htonl(0x0d); protocol = htons(0x05); /* get the TPM Endorsement Public Key */ ret = TPM_ReadPubek(&tpmpubkey); if (ret) return ret; /* convert the public key to OpenSSL format */ pubkey = TSS_convpubkey(&tpmpubkey); if (pubkey == NULL) return ERR_CRYPT_ERR; memset(ownerencr, 0, sizeof ownerencr); memset(srkencr, 0, sizeof srkencr); /* Pad and then encrypt the owner data using the RSA public key */ iret = RSA_padding_add_PKCS1_OAEP(padded, RSA_MODULUS_BYTE_SIZE, ownpass, TPM_HASH_SIZE, tpm_oaep_pad_str, sizeof tpm_oaep_pad_str); if (iret == 0) return ERR_CRYPT_ERR; iret = RSA_public_encrypt(RSA_MODULUS_BYTE_SIZE, padded, ownerencr, pubkey, RSA_NO_PADDING); if (iret < 0) return ERR_CRYPT_ERR; oencdatasize = htonl(iret); /* Pad and then encrypt the SRK data using the RSA public key */ iret = RSA_padding_add_PKCS1_OAEP(padded, RSA_MODULUS_BYTE_SIZE, spass, TPM_HASH_SIZE, tpm_oaep_pad_str, sizeof tpm_oaep_pad_str); if (iret == 0) return ERR_CRYPT_ERR; iret = RSA_public_encrypt(RSA_MODULUS_BYTE_SIZE, padded, srkencr, pubkey, RSA_NO_PADDING); if (iret < 0) return ERR_CRYPT_ERR; sencdatasize = htonl(iret); RSA_free(pubkey); if (ntohl(oencdatasize) < 0) return ERR_CRYPT_ERR; if (ntohl(sencdatasize) < 0) return ERR_CRYPT_ERR; /* fill the SRK-params key structure */ /* get tpm version */ ret = TPM_GetCapability(0x00000006, NULL, 0, &(srk.version[0]), &i); if (ret != 0) return ret; srk.keyusage = 0x0011; /* Storage Key */ srk.keyflags = 0; if (srkpass != NULL) srk.authdatausage = 0x01; else srk.authdatausage = 0x00; srk.privkeylen = 0; /* private key not specified here */ srk.pub.algorithm = 0x00000001; /* RSA */ srk.pub.encscheme = 0x0003; /* RSA OAEP SHA1 MGF1 */ srk.pub.sigscheme = 0x0001; /* NONE */ srk.pub.keybitlen = RSA_MODULUS_BIT_SIZE; srk.pub.numprimes = 2; srk.pub.expsize = 0; /* defaults to 0x010001 */ srk.pub.keylength = 0; /* not used here */ srk.pub.pcrinfolen = 0; /* not used here */ /* convert to a memory buffer */ srkparamsize = TPM_BuildKey(srk_param_buff, &srk); /* generate the odd nonce */ ret = TSS_gennonce(nonceodd); if (ret == 0) return ret; /* initiate the OIAP protocol */ ret = TSS_OIAPopen(&authhandle, nonceeven); if (ret != 0) return ret; /* calculate the Authorization Data */ ret = TSS_authhmac(authdata, ownpass, TPM_HASH_SIZE, nonceeven, nonceodd, 0, TPM_U32_SIZE, &command, TPM_U16_SIZE, &protocol, TPM_U32_SIZE, &oencdatasize, ntohl(oencdatasize), ownerencr, TPM_U32_SIZE, &sencdatasize, ntohl(sencdatasize), srkencr, srkparamsize, srk_param_buff, 0, 0); if (ret != 0) { TSS_OIAPclose(authhandle); return ret; } /* insert all the calculated fields into the request buffer */ ret = TSS_buildbuff(take_owner_fmt, tpmdata, command, protocol, ntohl(oencdatasize), ownerencr, ntohl(sencdatasize), srkencr, srkparamsize, srk_param_buff, authhandle, TPM_HASH_SIZE, nonceodd, TPM_HASH_SIZE, authdata); if ((ret & ERR_MASK) != 0) { TSS_OIAPclose(authhandle); return ret; } /* transmit the request buffer to the TPM device and read the reply */ ret = TPM_Transmit(tpmdata, "Take Ownership"); TSS_OIAPclose(authhandle); if (ret != 0) return ret; /* check the response HMAC */ srkparamsize = TSS_KeySize(tpmdata + TPM_DATA_OFFSET); ret = TSS_checkhmac1(tpmdata, command, nonceodd, ownpass, TPM_HASH_SIZE, srkparamsize, TPM_DATA_OFFSET, 0, 0); if (ret != 0) return ret; /* convert the returned key to a structure */ if (key == NULL) return 0; TSS_KeyExtract(tpmdata + TPM_DATA_OFFSET, key); return 0; }
int main(int argc, char *argv[]) { int ret; unsigned char hashpass1[TPM_HASH_SIZE]; /* hash of new key password */ unsigned char hashpass2[TPM_HASH_SIZE]; /* hash of migration password */ keydata k; /* keydata structure for input key parameters */ keydata q; /* keydata structure for resulting key */ RSA *rsa; /* OpenSSL format Public Key */ FILE *keyfile; /* output file for public key */ FILE *blbfile; /* output file for encrypted blob */ EVP_PKEY *pkey = NULL; /* OpenSSL public key */ char filename[256]; /* file name string of public key file */ unsigned char blob[4096]; /* area to hold key blob */ uint32_t bloblen; /* key blob length */ unsigned char *aptr1 = NULL; unsigned char *aptr2 = NULL; int nxtarg; TPM_setlog(0); /* turn off verbose output */ /* ** parse command line */ nxtarg = ParseArgs(argc, argv); (void)nxtarg; if ((digestfilename == NULL) || (keyname == NULL) || (parhandle == 0)) { printf("Missing parameter\n"); printUsage(); } if (-1 == readHMACandDigest(digestfilename, migAuthApproval, migAuthDigest)) { printf("Error reading from file %s.\n", digestfilename); exit(-1); } /* ** convert parent key handle from hex */ /* ** use the SHA1 hash of the password string as the Parent Key Authorization Data */ if (parpass != NULL) { TSS_sha1(parpass,strlen(parpass),hashpass1); aptr1 = hashpass1; } /* ** use the SHA1 hash of the password string as the Key Authorization Data */ if (keypass != NULL) { TSS_sha1(keypass,strlen(keypass),hashpass2); aptr2 = hashpass2; } /* ** initialize new key parameters */ k.v.tag = TPM_TAG_KEY12; k.keyFlags = TPM_MIGRATABLE | TPM_MIGRATEAUTHORITY; if (keypass != NULL) k.authDataUsage = 1; /* key requires authorization (password) */ else k.authDataUsage = 0; /* key requires no authorization (password) */ k.encData.size = 0; /* no private key specified here */ k.pub.algorithmParms.algorithmID = TPM_ALG_RSA; /* key algorithm 1 = RSA */ if (keytype == 's') { k.keyUsage = TPM_KEY_SIGNING; /* key Usage - 0x0010 = signing */ k.pub.algorithmParms.encScheme = TPM_ES_NONE; /* encryption scheme 1 = NONE - signing key */ k.pub.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1; /* signature scheme RSA/SHA1 */ } else if (keytype == 'd') { k.keyUsage = TPM_KEY_SIGNING; /* key Usage - 0x0010 = signing */ k.pub.algorithmParms.encScheme = TPM_ES_NONE; /* encryption scheme 1 = NONE - signing key */ k.pub.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_DER; /* signature scheme RSA/DER */ } else if (keytype == 'i') { k.keyUsage = TPM_KEY_SIGNING; /* key Usage - 0x0010 = signing */ k.pub.algorithmParms.encScheme = TPM_ES_NONE; /* encryption scheme 1 = NONE - signing key */ k.pub.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_INFO; /* signature scheme RSA/INFO */ } else if (keytype == 'e') { k.keyUsage = TPM_KEY_STORAGE; /* key Usage - 0x0011 = encryption */ k.pub.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1; /* encryption scheme 3 RSA */ k.pub.algorithmParms.sigScheme = TPM_SS_NONE; /* signature scheme NONE */ } else if (keytype == 'b') { k.keyUsage = TPM_KEY_BIND; /* key Usage - 0x0014 = bind */ k.pub.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1; /* encryption scheme 3 RSA */ k.pub.algorithmParms.sigScheme = TPM_SS_NONE; /* signature scheme none */ } else if (keytype == 'l') { k.keyUsage = TPM_KEY_LEGACY; /* key Usage - 0x0015 = legacy */ k.pub.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1; /* encryption scheme 3 RSA */ k.pub.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1; /* signature scheme RSA/SHA1 */ } else if (keytype == 'm') { k.keyUsage = TPM_KEY_MIGRATE; /* key Usage - 0x0016 = migration */ k.pub.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1; /* encryption scheme 3 RSA */ k.pub.algorithmParms.sigScheme = TPM_SS_NONE; /* signature scheme RSA/SHA1 */ } else { printUsage(); } k.pub.algorithmParms.u.rsaKeyParms.keyLength = keysize; /* RSA modulus size 2048 bits */ k.pub.algorithmParms.u.rsaKeyParms.numPrimes = 2; /* required */ k.pub.algorithmParms.u.rsaKeyParms.exponentSize = 0; /* RSA exponent - default 0x010001 */ k.pub.pubKey.keyLength = 0; /* key not specified here */ k.pub.pcrInfo.size = 0; /* no PCR's used at this time */ /* ** create and wrap an asymmetric key and get back the ** resulting keydata structure with the public and encrypted ** private keys filled in by the TPM */ bloblen = sizeof(blob); ret = TPM_CMK_CreateKey(parhandle, aptr1, aptr2, &k, migAuthApproval, migAuthDigest, &q, blob, &bloblen); if (ret != 0) { printf("Error %s from TPM_CMK_CreateKey\n", TPM_GetErrMsg(ret)); exit(-2); } sprintf(filename,"%s.key",keyname); blbfile = fopen(filename,"wb+"); if (blbfile == NULL) { printf("Unable to create key file\n"); exit(-3); } ret = fwrite(blob,1,bloblen,blbfile); if (ret != (int)bloblen) { printf("I/O Error writing key file\n"); exit(-4); } fclose(blbfile); /* ** convert the returned public key to OpenSSL format and ** export it to a file */ rsa = TSS_convpubkey(&(q.pub)); if (rsa == NULL) { printf("Error from TSS_convpubkey\n"); exit(-5); } OpenSSL_add_all_algorithms(); pkey = EVP_PKEY_new(); if (pkey == NULL) { printf("Unable to create EVP_PKEY\n"); exit(-6); } ret = EVP_PKEY_assign_RSA(pkey,rsa); if (ret == 0) { printf("Unable to assign public key to EVP_PKEY\n"); exit(-7); } sprintf(filename,"%s.pem",keyname); keyfile = fopen(filename,"wb"); if (keyfile == NULL) { printf("Unable to create public key file\n"); exit(-8); } ret = PEM_write_PUBKEY(keyfile,pkey); if (ret == 0) { printf("I/O Error writing public key file\n"); exit(-9); } fclose(keyfile); EVP_PKEY_free(pkey); exit(0); }
int main(int argc, char *argv[]) { int ret; unsigned char pass1hash[20]; unsigned char pass2hash[20]; keydata srk; RSA *rsa; /* OpenSSL format Public Key */ FILE *keyfile; /* output file for public key */ EVP_PKEY *pkey = NULL; /* OpenSSL public key */ if (argc < 2) { printf("Usage: takeown <owner password> [<storage root key password>]\n"); exit(1); } TPM_setlog(0); /* turn off verbose output */ /* ** use the SHA1 hash of the password string as the Owner Authorization Data */ TSS_sha1((unsigned char*)argv[1],strlen(argv[1]),pass1hash); /* ** use the SHA1 hash of the password string as the SRK Authorization Data */ if (argc > 2) { TSS_sha1((unsigned char *)argv[2],strlen(argv[2]),pass2hash); ret = TPM_TakeOwnership12(pass1hash,pass2hash,&srk); } else { TSS_sha1((unsigned char *)"SRK PWD",8,pass2hash); /* hard code for tpmdiag */ ret = TPM_TakeOwnership12(pass1hash,pass2hash,&srk); } if (ret != 0) { printf("Error %s from TPM_TakeOwnership\n",TPM_GetErrMsg(ret)); exit(2); } /* ** convert the returned public key to OpenSSL format and ** export it to a file */ rsa = TSS_convpubkey(&(srk.pub)); if (rsa == NULL) { printf("Error from TSS_convpubkey\n"); exit(3); } OpenSSL_add_all_algorithms(); pkey = EVP_PKEY_new(); if (pkey == NULL) { printf("Unable to create EVP_PKEY\n"); exit(4); } ret = EVP_PKEY_assign_RSA(pkey,rsa); keyfile = fopen("srk.pem","wb"); if (keyfile == NULL) { printf("Unable to create public key file\n"); exit(5); } ret = PEM_write_PUBKEY(keyfile,pkey); if (ret == 0) { printf("Unable to write public key file\n"); exit(6); } fclose(keyfile); EVP_PKEY_free(pkey); exit(0); }
int main(int argc, char *argv[]) { int ret = 0; TPM_BOOL reset = TRUE; unsigned char *passptr1; char * password = NULL; unsigned char passhash1[20]; /* hash of password */ pubkeydata pubek; int i = 1; TPM_setlog(0); while (i < argc) { if (!strcmp(argv[i],"-pwdk")) { i++; if (i >= argc) { printf("Parameter missing for -pwdk option!\n"); usage(); } reset = FALSE; password = argv[i]; } else if (!strcmp(argv[i],"-v")) { TPM_setlog(1); } else if (!strcmp(argv[i],"-h")) { usage(); } else { printf("\n%s is not a valid option\n",argv[i]); usage(); } i++; } if (password != NULL) { TSS_sha1(password,strlen(password),passhash1); passptr1 = passhash1; } else { passptr1 = NULL; } ret = TPM_CreateRevocableEK(reset, passptr1, &pubek); if (0 != ret) { printf("Error %s from TPM_CreateRevocableEK\n", TPM_GetErrMsg(ret)); } else { EVP_PKEY *pkey = NULL; /* OpenSSL public key */ FILE * keyfile; RSA * rsa; /* ** convert the returned public key to OpenSSL format and ** export it to a file */ rsa = TSS_convpubkey(&pubek); if (rsa == NULL) { printf("Error from TSS_convpubkey\n"); exit(-3); } OpenSSL_add_all_algorithms(); pkey = EVP_PKEY_new(); if (pkey == NULL) { printf("Unable to create EVP_PKEY\n"); exit(-4); } ret = EVP_PKEY_assign_RSA(pkey,rsa); if (ret == 0) { printf("Unable to assign public key to EVP_PKEY\n"); exit(-5); } keyfile = fopen("pubek.pem","wb"); if (keyfile == NULL) { printf("Unable to create public key file\n"); exit(-6); } ret = PEM_write_PUBKEY(keyfile,pkey); if (ret == 0) { printf("Unable to write public key file\n"); exit(-7); } printf("pubek.pem successfully written\n"); printf("Pubek keylength %d\nModulus:",pubek.pubKey.keyLength); for(i=0;i<(int)pubek.pubKey.keyLength;i++){ if(!(i%16)) printf("\n"); printf("%02X ",pubek.pubKey.modulus[i]); } printf("\n"); fclose(keyfile); EVP_PKEY_free(pkey); ret = 0; } exit(ret); }