/** * gnutls_pubkey_import_tpm_url: * @pkey: The public key * @url: The URL of the TPM key to be imported * @srk_password: The password for the SRK key (optional) * @flags: should be zero * * This function will import the given private key to the abstract * #gnutls_privkey_t type. * * Note that unless %GNUTLS_PUBKEY_DISABLE_CALLBACKS * is specified, if incorrect (or NULL) passwords are given * the PKCS11 callback functions will be used to obtain the * correct passwords. Otherwise if the SRK password is wrong * %GNUTLS_E_TPM_SRK_PASSWORD_ERROR is returned. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.1.0 * **/ int gnutls_pubkey_import_tpm_url(gnutls_pubkey_t pkey, const char *url, const char *srk_password, unsigned int flags) { struct tpmkey_url_st durl; gnutls_datum_t fdata = { NULL, 0 }; int ret; CHECK_INIT; ret = decode_tpmkey_url(url, &durl); if (ret < 0) return gnutls_assert_val(ret); if (durl.filename) { ret = gnutls_load_file(durl.filename, &fdata); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_pubkey_import_tpm_raw(pkey, &fdata, GNUTLS_TPMKEY_FMT_CTK_PEM, srk_password, flags); if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) ret = gnutls_pubkey_import_tpm_raw(pkey, &fdata, GNUTLS_TPMKEY_FMT_RAW, srk_password, flags); if (ret < 0) { gnutls_assert(); goto cleanup; } } else if (durl.uuid_set) { if (flags & GNUTLS_PUBKEY_DISABLE_CALLBACKS) ret = import_tpm_pubkey(pkey, NULL, 0, &durl.uuid, durl.storage, srk_password); else ret = import_tpm_pubkey_cb(pkey, NULL, 0, &durl.uuid, durl.storage, srk_password); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = 0; cleanup: gnutls_free(fdata.data); clear_tpmkey_url(&durl); return ret; }
static int decode_tpmkey_url(const char *url, struct tpmkey_url_st *s) { char *p; size_t size; int ret; unsigned int i, j; if (strstr(url, "tpmkey:") == NULL) return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); memset(s, 0, sizeof(*s)); p = strstr(url, "file="); if (p != NULL) { p += sizeof("file=") - 1; size = strlen(p); s->filename = gnutls_malloc(size + 1); if (s->filename == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ret = unescape_string(s->filename, p, &size, ';'); if (ret < 0) { gnutls_assert(); goto cleanup; } s->filename[size] = 0; } else if ((p = strstr(url, "uuid=")) != NULL) { char tmp_uuid[33]; uint8_t raw_uuid[16]; p += sizeof("uuid=") - 1; size = strlen(p); for (j = i = 0; i < size; i++) { if (j == sizeof(tmp_uuid) - 1) { break; } if (c_isalnum(p[i])) tmp_uuid[j++] = p[i]; } tmp_uuid[j] = 0; size = sizeof(raw_uuid); ret = _gnutls_hex2bin(tmp_uuid, strlen(tmp_uuid), raw_uuid, &size); if (ret < 0) { gnutls_assert(); goto cleanup; } memcpy(&s->uuid.ulTimeLow, raw_uuid, 4); memcpy(&s->uuid.usTimeMid, &raw_uuid[4], 2); memcpy(&s->uuid.usTimeHigh, &raw_uuid[6], 2); s->uuid.bClockSeqHigh = raw_uuid[8]; s->uuid.bClockSeqLow = raw_uuid[9]; memcpy(&s->uuid.rgbNode, &raw_uuid[10], 6); s->uuid_set = 1; } else { return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); } if ((p = strstr(url, "storage=user")) != NULL) s->storage = TSS_PS_TYPE_USER; else s->storage = TSS_PS_TYPE_SYSTEM; return 0; cleanup: clear_tpmkey_url(s); return ret; }