int run_sample()

in kmsp11/sample/sample.c [36:172]


int run_sample(const char* library_path, const char* config_file_path,
               const char* ec_p256_signing_key_id) {
  // Dynamically load the PKCS#11 shared library.
  // Note that there should be no corresponding dlclose call. Our library does
  // not support being dynamically unloaded.
  void* library = dlopen(library_path, RTLD_LAZY | RTLD_NODELETE);
  if (!library) {
    fprintf(stderr, "error loading libkmsp11.so");
    return 1;
  }

  // Dynamically load the function list table from the loaded library.
  CK_C_GetFunctionList get_function_list =
      (CK_C_GetFunctionList)dlsym(library, "C_GetFunctionList");
  if (!get_function_list) {
    fprintf(stderr, "error locating C_GetFunctionList in the loaded library");
    return 1;
  }

  // Load the function list into 'f'.
  CK_FUNCTION_LIST* f;
  CK_RV rv = get_function_list(&f);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_GetFunctionList", rv);
    return 1;
  }

  // Initialize the library.
  CK_C_INITIALIZE_ARGS init_args = {0};
  init_args.flags = CKF_OS_LOCKING_OK;
  init_args.pReserved = (char*)config_file_path;
  rv = f->C_Initialize(&init_args);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_Initialize", rv);
    return 1;
  }

  // Open a session handle.
  CK_SESSION_HANDLE sess;
  rv = f->C_OpenSession(/*slotID=*/0, /*flags=*/CKF_SERIAL_SESSION,
                        /*pApplication=*/0, /*Notify=*/0, &sess);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_OpenSession", rv);
    goto library_cleanup;
  }

  // Begin searching for our signing key.
  CK_OBJECT_CLASS object_class = CKO_PRIVATE_KEY;
  CK_ATTRIBUTE template[] = {
      {CKA_CLASS, &object_class, sizeof(object_class)},
      {CKA_LABEL, (CK_UTF8CHAR*)ec_p256_signing_key_id,
       strlen(ec_p256_signing_key_id)},
  };
  rv = f->C_FindObjectsInit(sess, template, 2);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_FindObjectsInit", rv);
    goto session_cleanup;
  }

  // Retrieve the handle to the signing key.
  CK_OBJECT_HANDLE private_key;
  CK_ULONG found_count;
  rv = f->C_FindObjects(sess, &private_key, 1, &found_count);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_FindObjects", rv);
    goto session_cleanup;
  }
  if (found_count != 1) {
    fprintf(stderr, "found_count=%ld after calling C_FindObjects", found_count);
    goto session_cleanup;
  }

  // End the search.
  rv = f->C_FindObjectsFinal(sess);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_FindObjectsFinal", rv);
    goto session_cleanup;
  }

  // Initialize our signing operation.
  CK_MECHANISM mech = {CKM_ECDSA, 0, 0};
  rv = f->C_SignInit(sess, &mech, private_key);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_SignInit", rv);
    goto session_cleanup;
  }

  // Prepare to call 'Sign'.

  // When calling Sign, `data` should be filled with the SHA-256 digest of the
  // data to be signed over.
  CK_BYTE data[32] = {0};
  // An output buffer to hold the computed signature.
  CK_BYTE signature[64] = {0};

  // Call 'Sign'.
  CK_ULONG signature_length = sizeof(signature);
  rv = f->C_Sign(sess, data, sizeof(data), signature, &signature_length);
  if (rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_Sign", rv);
    goto session_cleanup;
  }
  if (signature_length != sizeof(signature)) {
    fprintf(stderr,
            "unexpected signature length = %ld (want %ld) after calling C_Sign",
            signature_length, sizeof(signature));
    goto session_cleanup;
  }

  printf("computed signature: ");
  for (size_t i = 0; i < sizeof(signature); i++) {
    printf("%X", signature[i]);
  }
  printf("\n");

  CK_RV cleanup_rv;

session_cleanup:
  cleanup_rv = f->C_CloseSession(sess);
  if (cleanup_rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_CloseSession", rv);
    if (rv == CKR_OK) {
      rv = cleanup_rv;
    }
  }

library_cleanup:
  cleanup_rv = f->C_Finalize(0);
  if (cleanup_rv != CKR_OK) {
    fprintf(stderr, "CK_RV=%lX calling C_Finalize", rv);
    if (rv == CKR_OK) {
      rv = cleanup_rv;
    }
  }

  return rv;
}