absl::StatusOr ExtractKeyGenerationParams()

in kmsp11/session.cc [40:127]


absl::StatusOr<KeyGenerationParams> ExtractKeyGenerationParams(
    absl::Span<const CK_ATTRIBUTE> prv_template, bool allow_software_keys) {
  std::optional<std::string> label;
  std::optional<kms_v1::CryptoKeyVersion::CryptoKeyVersionAlgorithm> algorithm;
  std::optional<kms_v1::ProtectionLevel> protection_level;

  for (const CK_ATTRIBUTE& attr : prv_template) {
    switch (attr.type) {
      case CKA_LABEL:
        label =
            std::string(reinterpret_cast<char*>(attr.pValue), attr.ulValueLen);
        static std::regex* label_regexp = new std::regex("[a-zA-Z0-9_-]{1,63}");
        if (!std::regex_match(*label, *label_regexp)) {
          return NewInvalidArgumentError(
              "CKA_LABEL must be a valid Cloud KMS CryptoKey ID",
              CKR_ATTRIBUTE_VALUE_INVALID, SOURCE_LOCATION);
        }

        break;
      case CKA_KMS_ALGORITHM:
        if (attr.ulValueLen != sizeof(CK_ULONG)) {
          return NewInvalidArgumentError(
              absl::StrFormat("CKA_KMS_ALGORITHM value should be CK_ULONG "
                              "(size=%d, got=%d)",
                              sizeof(CK_ULONG), attr.ulValueLen),
              CKR_ATTRIBUTE_VALUE_INVALID, SOURCE_LOCATION);
        }
        algorithm = kms_v1::CryptoKeyVersion::CryptoKeyVersionAlgorithm(
            *static_cast<CK_ULONG*>(attr.pValue));
        break;
      case CKA_KMS_PROTECTION_LEVEL:
        if (attr.ulValueLen != sizeof(CK_ULONG)) {
          return NewInvalidArgumentError(
              absl::StrFormat(
                  "CKA_KMS_PROTECTION_LEVEL value should be CK_ULONG "
                  "(size=%d, got=%d)",
                  sizeof(CK_ULONG), attr.ulValueLen),
              CKR_ATTRIBUTE_VALUE_INVALID, SOURCE_LOCATION);
        }
        protection_level =
            kms_v1::ProtectionLevel(*static_cast<CK_ULONG*>(attr.pValue));
        if (protection_level != kms_v1::SOFTWARE &&
            protection_level != kms_v1::HSM) {
          return NewInvalidArgumentError(
              absl::StrFormat("CKA_KMS_PROTECTION_LEVEL value should be "
                              "1(SOFTWARE) or 2(HSM) "
                              ", got=%d",
                              attr.ulValueLen),
              CKR_ATTRIBUTE_VALUE_INVALID, SOURCE_LOCATION);
        }
        if (protection_level == kms_v1::SOFTWARE && !allow_software_keys) {
          return NewInvalidArgumentError(
              "CKA_KMS_PROTECTION_LEVEL cannot be SOFTWARE because only keys "
              "with protection level = HSM are "
              "allowed. If you want to be able to create software keys, use "
              "allow_software_keys in the "
              "configuration.",
              CKR_ATTRIBUTE_VALUE_INVALID, SOURCE_LOCATION);
        }
        break;
      default:
        return NewInvalidArgumentError(
            absl::StrFormat(
                "this token does not permit specifying attribute type %#x",
                attr.type),
            CKR_TEMPLATE_INCONSISTENT, SOURCE_LOCATION);
    }
  }

  if (!label.has_value()) {
    return NewInvalidArgumentError("CKA_LABEL must be specified for the key",
                                   CKR_TEMPLATE_INCOMPLETE, SOURCE_LOCATION);
  }
  if (!algorithm.has_value()) {
    return NewInvalidArgumentError(
        "CKA_KMS_ALGORITHM must be specified for the key",
        CKR_TEMPLATE_INCOMPLETE, SOURCE_LOCATION);
  }

  absl::StatusOr<AlgorithmDetails> algorithm_details = GetDetails(*algorithm);
  if (!algorithm_details.ok()) {
    return NewInvalidArgumentError(algorithm_details.status().message(),
                                   CKR_ATTRIBUTE_VALUE_INVALID,
                                   SOURCE_LOCATION);
  }

  return KeyGenerationParams{*label, *algorithm_details, protection_level};
}