static HCERTSTORE open_cert_db()

in c/src/ssl/schannel.cpp [1881:1971]


static HCERTSTORE open_cert_db(const char *store_name, const char *passwd, int *error) {
  *error = 0;
  DWORD sys_store_type = 0;
  HCERTSTORE cert_store = 0;

  if (store_name) {
    if (strncmp(store_name, "ss:", 3) == 0) {
      store_name += 3;
      sys_store_type = CERT_SYSTEM_STORE_CURRENT_USER;
    }
    else if (strncmp(store_name, "lmss:", 5) == 0) {
      store_name += 5;
      sys_store_type = CERT_SYSTEM_STORE_LOCAL_MACHINE;
    }
  }

  if (sys_store_type) {
    // Opening a system store, names are not case sensitive.
    // Map confusing GUI name to actual registry store name.
    if (!pn_strcasecmp(store_name, "personal")) store_name= "my";
    cert_store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, NULL,
                               CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG |
                               sys_store_type, store_name);
    if (!cert_store) {
      ssl_log_error_status(GetLastError(), "Failed to open system certificate store %s", store_name);
      *error = -3;
      return NULL;
    }
  } else {
    // PKCS#12 file
    HANDLE cert_file = CreateFile(store_name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
                                  FILE_ATTRIBUTE_NORMAL, NULL);
    if (INVALID_HANDLE_VALUE == cert_file) {
      HRESULT status = GetLastError();
      ssl_log_error_status(status, "Failed to open the file holding the private key: %s", store_name);
      *error = -4;
      return NULL;
    }
    DWORD nread = 0L;
    const DWORD file_size = GetFileSize(cert_file, NULL);
    char *buf = NULL;
    if (INVALID_FILE_SIZE != file_size)
      buf = (char *) malloc(file_size);
    if (!buf || !ReadFile(cert_file, buf, file_size, &nread, NULL)
        || file_size != nread) {
      HRESULT status = GetLastError();
      CloseHandle(cert_file);
      free(buf);
      ssl_log_error_status(status, "Reading the private key from file failed %s", store_name);
      *error = -5;
      return NULL;
    }
    CloseHandle(cert_file);

    CRYPT_DATA_BLOB blob;
    blob.cbData = nread;
    blob.pbData = (BYTE *) buf;

    wchar_t *pwUCS2 = NULL;
    int pwlen = 0;
    if (passwd) {
      // convert passwd to null terminated wchar_t (Windows UCS2)
      pwlen = strlen(passwd);
      pwUCS2 = (wchar_t *) calloc(pwlen + 1, sizeof(wchar_t));
      int nwc = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, passwd, pwlen, &pwUCS2[0], pwlen);
      if (!nwc) {
        ssl_log_error_status(GetLastError(), "Error converting password from UTF8");
        free(buf);
        free(pwUCS2);
        *error = -6;
        return NULL;
      }
    }

    cert_store = PFXImportCertStore(&blob, pwUCS2, 0);
    if (pwUCS2) {
      SecureZeroMemory(pwUCS2, pwlen * sizeof(wchar_t));
      free(pwUCS2);
    }
    if (cert_store == NULL) {
      ssl_log_error_status(GetLastError(), "Failed to import the file based certificate store");
      free(buf);
      *error = -7;
      return NULL;
    }

    free(buf);
  }

  return cert_store;
}