Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ finally

## Features

- **Key Encapsulation Mechanisms (KEMs)**: ML-KEM, Kyber, FrodoKEM, and more
- **Digital Signatures**: ML-DSA, Dilithium, Falcon, SPHINCS+, and more
- **Key Encapsulation Mechanisms (KEMs)**: ML-KEM, Kyber, BIKE, HQC, Classic McEliece, NTRU Prime, FrodoKEM
- **Digital Signatures**: ML-DSA, Dilithium, Falcon, SPHINCS+, MAYO, CROSS, UOV
- **Type-safe API**: Strong typing with enums for algorithms and proper resource management
- **Memory management**: Automatic cleanup of native resources using IDisposable pattern
- **Cross-platform**: Supports Windows x64, Windows ARM64, macOS ARM64, Linux x64, and Linux ARM64
Expand All @@ -126,14 +126,21 @@ finally

- **ML-KEM** (NIST standardized): ML-KEM-512, ML-KEM-768, ML-KEM-1024
- **Kyber**: Kyber512, Kyber768, Kyber1024
- **BIKE**: BIKE-L1, BIKE-L3, BIKE-L5
- **HQC**: HQC-128, HQC-192, HQC-256
- **Classic McEliece**: All 10 variants (e.g., 348864, 460896, 6688128, 6960119, 8192128 with fast variants)
- **NTRU Prime**: sntrup761
- **FrodoKEM**: FrodoKEM-640-AES, FrodoKEM-640-SHAKE, FrodoKEM-976-AES, FrodoKEM-976-SHAKE, FrodoKEM-1344-AES, FrodoKEM-1344-SHAKE

### Digital Signatures

- **ML-DSA** (NIST standardized): ML-DSA-44, ML-DSA-65, ML-DSA-87
- **Dilithium**: Dilithium2, Dilithium3, Dilithium5
- **Falcon**: Falcon-512, Falcon-1024
- **SPHINCS+**: Various parameter sets
- **Falcon**: Falcon-512, Falcon-1024, Falcon-Padded-512, Falcon-Padded-1024
- **SPHINCS+**: All "simple" variants (SHA2 and SHAKE, 128/192/256, fast/small)
- **MAYO**: MAYO-1, MAYO-2, MAYO-3, MAYO-5
- **CROSS**: All 18 variants (RSDP/RSDPG, Balanced/Fast/Small)
- **UOV**: All 12 variants (Ip, Is, III, V; with pkc/skc variants)

## Algorithm Availability

Expand Down Expand Up @@ -222,7 +229,7 @@ git submodule update
This will:
- Configure and build liboqs as a shared library
- Copy the resulting DLL/so/dylib to the appropriate directories
- Enable common quantum-resistant algorithms (ML-KEM, ML-DSA, Kyber, Dilithium, Falcon, FrodoKEM)
- Enable all common quantum-resistant algorithms (ML-KEM, ML-DSA, Kyber, Dilithium, Falcon, FrodoKEM, BIKE, HQC, SPHINCS+, etc.)

2. **Build the .NET libraries:**

Expand Down
8 changes: 8 additions & 0 deletions build-dotnet-liboqs-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,17 @@ CMAKE_ARGS="$CMAKE_ARGS -DOQS_PERMIT_UNSUPPORTED_ARCHITECTURE=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_ML_KEM=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_KYBER=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_FRODOKEM=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_BIKE=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_HQC=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_NTRUPRIME=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_KEM_CLASSIC_MCELIECE=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_ML_DSA=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_DILITHIUM=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_FALCON=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_SPHINCS=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_MAYO=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_CROSS=ON"
CMAKE_ARGS="$CMAKE_ARGS -DOQS_ENABLE_SIG_UOV=ON"

# Add toolchain file if specified
if [ -n "$CMAKE_TOOLCHAIN_FILE" ]; then
Expand Down
10 changes: 9 additions & 1 deletion build-dotnet-liboqs-macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,17 @@ cmake .. \
-DOQS_ENABLE_KEM_ML_KEM=ON \
-DOQS_ENABLE_KEM_KYBER=ON \
-DOQS_ENABLE_KEM_FRODOKEM=ON \
-DOQS_ENABLE_KEM_BIKE=ON \
-DOQS_ENABLE_KEM_HQC=ON \
-DOQS_ENABLE_KEM_NTRUPRIME=ON \
-DOQS_ENABLE_KEM_CLASSIC_MCELIECE=ON \
-DOQS_ENABLE_SIG_ML_DSA=ON \
-DOQS_ENABLE_SIG_DILITHIUM=ON \
-DOQS_ENABLE_SIG_FALCON=ON
-DOQS_ENABLE_SIG_FALCON=ON \
-DOQS_ENABLE_SIG_SPHINCS=ON \
-DOQS_ENABLE_SIG_MAYO=ON \
-DOQS_ENABLE_SIG_CROSS=ON \
-DOQS_ENABLE_SIG_UOV=ON

echo "Building liboqs..."
cmake --build . --config "$CONFIGURATION"
Expand Down
7 changes: 7 additions & 0 deletions build-dotnet-liboqs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,16 @@ try {
"-DOQS_ENABLE_KEM_ML_KEM=ON"
"-DOQS_ENABLE_KEM_KYBER=ON"
"-DOQS_ENABLE_KEM_FRODOKEM=ON"
"-DOQS_ENABLE_KEM_HQC=ON"
"-DOQS_ENABLE_KEM_NTRUPRIME=ON"
"-DOQS_ENABLE_KEM_CLASSIC_MCELIECE=ON"
"-DOQS_ENABLE_SIG_ML_DSA=ON"
"-DOQS_ENABLE_SIG_DILITHIUM=ON"
"-DOQS_ENABLE_SIG_FALCON=ON"
"-DOQS_ENABLE_SIG_SPHINCS=ON"
"-DOQS_ENABLE_SIG_MAYO=ON"
"-DOQS_ENABLE_SIG_CROSS=ON"
"-DOQS_ENABLE_SIG_UOV=ON"
)

& cmake @cmakeArgs
Expand Down
70 changes: 43 additions & 27 deletions samples/Examples/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Text;
using LibOQS.NET;
using Spectre.Console;
using System.Text;

namespace Examples;

Expand All @@ -22,19 +22,19 @@ static void Main(string[] args)
new SelectionPrompt<string>()
.Title("Choose the [green]demo[/] to run?")
.AddChoices([
"ML-KEM (Key Encapsulation)",
"ML-DSA (Digital Signature)",
"KEM (Key Encapsulation)",
"DSA (Digital Signature)",
"Signed Key Exchange",
"Algorithm Comparison",
"Exit"
]));

switch (demo)
{
case "ML-KEM (Key Encapsulation)":
case "KEM (Key Encapsulation)":
LibOqsDemo.RunMlKem();
break;
case "ML-DSA (Digital Signature)":
case "DSA (Digital Signature)":
LibOqsDemo.RunMlDsa();
break;
case "Signed Key Exchange":
Expand All @@ -55,23 +55,27 @@ public static class LibOqsDemo
{
public static void RunMlDsa()
{
AnsiConsole.Write(new Rule("[blue]ML-DSA Digital Signature Demo[/]").RuleStyle("blue"));
AnsiConsole.Write(new Rule("[blue]Digital Signature Demo[/]").RuleStyle("blue"));

var enabledAlgorithms = Enum.GetValues<SigAlgorithm>()
.Where(a => a.IsEnabled())
.ToList();

var algorithm = AnsiConsole.Prompt(
new SelectionPrompt<SigAlgorithm>()
.Title("Select a [green]Signature Algorithm[/] to demo:")
.PageSize(10)
.AddChoices(enabledAlgorithms));

var raw = "Hello, ML-DSA from LibOQS.NET!";
var raw = $"Hello, {algorithm} from LibOQS.NET!";
var data = Encoding.UTF8.GetBytes(raw);

PrintPanel("Message", [
$"Raw: {raw}",
$"Encoded: {data.PrettyPrint()}"
]);

if (!SigAlgorithm.MlDsa65.IsEnabled())
{
PrintPanel("Error", ["ML-DSA-65 is not enabled in this build"]);
return;
}

using var sig = new SigInstance(SigAlgorithm.MlDsa65);
using var sig = new SigInstance(algorithm);

// Generate key pair
var (publicKey, secretKey) = sig.GenerateKeypair();
Expand Down Expand Up @@ -103,15 +107,19 @@ public static void RunMlDsa()

public static void RunMlKem()
{
AnsiConsole.Write(new Rule("[green]ML-KEM Key Encapsulation Demo[/]").RuleStyle("green"));
AnsiConsole.Write(new Rule("[green]Key Encapsulation Demo[/]").RuleStyle("green"));

if (!KemAlgorithm.MlKem768.IsEnabled())
{
PrintPanel("Error", ["ML-KEM-768 is not enabled in this build"]);
return;
}
var enabledAlgorithms = Enum.GetValues<KemAlgorithm>()
.Where(a => a.IsEnabled())
.ToList();

var algorithm = AnsiConsole.Prompt(
new SelectionPrompt<KemAlgorithm>()
.Title("Select a [green]KEM Algorithm[/] to demo:")
.PageSize(10)
.AddChoices(enabledAlgorithms));

using var kem = new KemInstance(KemAlgorithm.MlKem768);
using var kem = new KemInstance(algorithm);

// Generate Alice's key pair
var (alicePublicKey, aliceSecretKey) = kem.GenerateKeypair();
Expand Down Expand Up @@ -251,9 +259,9 @@ public static void RunAlgorithmComparison()

var secLevel = kemAlg switch
{
KemAlgorithm.MlKem512 or KemAlgorithm.Kyber512 => "Level 1",
KemAlgorithm.MlKem768 or KemAlgorithm.Kyber768 => "Level 3",
KemAlgorithm.MlKem1024 or KemAlgorithm.Kyber1024 => "Level 5",
KemAlgorithm.MlKem512 or KemAlgorithm.Kyber512 or KemAlgorithm.BikeL1 or KemAlgorithm.Hqc128 or KemAlgorithm.ClassicMcEliece348864 => "Level 1",
KemAlgorithm.MlKem768 or KemAlgorithm.Kyber768 or KemAlgorithm.BikeL3 or KemAlgorithm.Hqc192 or KemAlgorithm.NtruPrimeSntrup761 or KemAlgorithm.ClassicMcEliece460896 => "Level 3",
KemAlgorithm.MlKem1024 or KemAlgorithm.Kyber1024 or KemAlgorithm.BikeL5 or KemAlgorithm.Hqc256 or KemAlgorithm.ClassicMcEliece6688128 or KemAlgorithm.ClassicMcEliece6960119 or KemAlgorithm.ClassicMcEliece8192128 => "Level 5",
_ when kemAlg.ToString().Contains("640") => "Level 1",
_ when kemAlg.ToString().Contains("976") => "Level 3",
_ when kemAlg.ToString().Contains("1344") => "Level 5",
Expand Down Expand Up @@ -289,10 +297,18 @@ _ when kemAlg.ToString().Contains("1344") => "Level 5",

var secLevel = sigAlg switch
{
SigAlgorithm.MlDsa44 or SigAlgorithm.Dilithium2 or SigAlgorithm.Falcon512 => "Level 1",
SigAlgorithm.MlDsa44 or SigAlgorithm.Dilithium2 or SigAlgorithm.Falcon512 or SigAlgorithm.FalconPadded512 => "Level 1",
SigAlgorithm.MlDsa65 or SigAlgorithm.Dilithium3 => "Level 3",
SigAlgorithm.MlDsa87 or SigAlgorithm.Dilithium5 or SigAlgorithm.Falcon1024 => "Level 5",
SigAlgorithm.MlDsa87 or SigAlgorithm.Dilithium5 or SigAlgorithm.Falcon1024 or SigAlgorithm.FalconPadded1024 => "Level 5",
_ when sigAlg.ToString().Contains("128") => "Level 1",
_ when sigAlg.ToString().Contains("192") => "Level 3",
_ when sigAlg.ToString().Contains("256") => "Level 5",
_ when sigAlg.ToString().Contains("Mayo1") || sigAlg.ToString().Contains("Mayo2") => "Level 1",
_ when sigAlg.ToString().Contains("Mayo3") => "Level 3",
_ when sigAlg.ToString().Contains("Mayo5") => "Level 5",
_ when sigAlg.ToString().Contains("OvIs") || sigAlg.ToString().Contains("OvIp") => "Level 1",
_ when sigAlg.ToString().Contains("OvIii") => "Level 3",
_ when sigAlg.ToString().Contains("OvV") => "Level 5",
_ => "Various"
};

Expand Down
17 changes: 17 additions & 0 deletions src/LibOQS.NET.Native/Kem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,23 @@ public struct OqsKem
public static readonly string OQS_KEM_alg_kyber_512 = "Kyber512";
public static readonly string OQS_KEM_alg_kyber_768 = "Kyber768";
public static readonly string OQS_KEM_alg_kyber_1024 = "Kyber1024";
public static readonly string OQS_KEM_alg_bike_l1 = "BIKE-L1";
public static readonly string OQS_KEM_alg_bike_l3 = "BIKE-L3";
public static readonly string OQS_KEM_alg_bike_l5 = "BIKE-L5";
public static readonly string OQS_KEM_alg_hqc_128 = "HQC-128";
public static readonly string OQS_KEM_alg_hqc_192 = "HQC-192";
public static readonly string OQS_KEM_alg_hqc_256 = "HQC-256";
public static readonly string OQS_KEM_alg_ntruprime_sntrup761 = "sntrup761";
public static readonly string OQS_KEM_alg_classic_mceliece_348864 = "Classic-McEliece-348864";
public static readonly string OQS_KEM_alg_classic_mceliece_348864f = "Classic-McEliece-348864f";
public static readonly string OQS_KEM_alg_classic_mceliece_460896 = "Classic-McEliece-460896";
public static readonly string OQS_KEM_alg_classic_mceliece_460896f = "Classic-McEliece-460896f";
public static readonly string OQS_KEM_alg_classic_mceliece_6688128 = "Classic-McEliece-6688128";
public static readonly string OQS_KEM_alg_classic_mceliece_6688128f = "Classic-McEliece-6688128f";
public static readonly string OQS_KEM_alg_classic_mceliece_6960119 = "Classic-McEliece-6960119";
public static readonly string OQS_KEM_alg_classic_mceliece_6960119f = "Classic-McEliece-6960119f";
public static readonly string OQS_KEM_alg_classic_mceliece_8192128 = "Classic-McEliece-8192128";
public static readonly string OQS_KEM_alg_classic_mceliece_8192128f = "Classic-McEliece-8192128f";
public static readonly string OQS_KEM_alg_frodokem_640_aes = "FrodoKEM-640-AES";
public static readonly string OQS_KEM_alg_frodokem_640_shake = "FrodoKEM-640-SHAKE";
public static readonly string OQS_KEM_alg_frodokem_976_aes = "FrodoKEM-976-AES";
Expand Down
2 changes: 1 addition & 1 deletion src/LibOQS.NET.Native/LibOQS.NET.Native.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Nullable>enable</Nullable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>LibOQS.NET.Native</PackageId>
<PackageVersion>0.1.3</PackageVersion>
<PackageVersion>0.2.0</PackageVersion>
<Authors>filipw</Authors>
<Description>Native P/Invoke bindings for liboqs - a C library for quantum-resistant cryptographic algorithms</Description>
<PackageProjectUrl>https://github.com/filipw/maybe-liboqs-dotnet</PackageProjectUrl>
Expand Down
56 changes: 50 additions & 6 deletions src/LibOQS.NET.Native/Sig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ public struct OqsSig
/// Sign a message
/// </summary>
[DllImport(Common.LibraryName, CallingConvention = CallingConvention.Cdecl)]
public static extern Common.OqsStatus OQS_SIG_sign(IntPtr sig, IntPtr signature, ref UIntPtr signature_len,
public static extern Common.OqsStatus OQS_SIG_sign(IntPtr sig, IntPtr signature, ref UIntPtr signature_len,
IntPtr message, UIntPtr message_len, IntPtr secret_key);

/// <summary>
/// Verify a signature
/// </summary>
[DllImport(Common.LibraryName, CallingConvention = CallingConvention.Cdecl)]
public static extern Common.OqsStatus OQS_SIG_verify(IntPtr sig, IntPtr message, UIntPtr message_len,
public static extern Common.OqsStatus OQS_SIG_verify(IntPtr sig, IntPtr message, UIntPtr message_len,
IntPtr signature, UIntPtr signature_len, IntPtr public_key);

/// <summary>
Expand Down Expand Up @@ -84,8 +84,52 @@ public static extern Common.OqsStatus OQS_SIG_verify(IntPtr sig, IntPtr message,
public static readonly string OQS_SIG_alg_dilithium5 = "Dilithium5";
public static readonly string OQS_SIG_alg_falcon_512 = "Falcon-512";
public static readonly string OQS_SIG_alg_falcon_1024 = "Falcon-1024";
public static readonly string OQS_SIG_alg_sphincs_haraka_128f_robust = "SPHINCS+-Haraka-128f-robust";
public static readonly string OQS_SIG_alg_sphincs_haraka_128f_simple = "SPHINCS+-Haraka-128f-simple";
public static readonly string OQS_SIG_alg_sphincs_haraka_128s_robust = "SPHINCS+-Haraka-128s-robust";
public static readonly string OQS_SIG_alg_sphincs_haraka_128s_simple = "SPHINCS+-Haraka-128s-simple";
public static readonly string OQS_SIG_alg_falcon_padded_512 = "Falcon-padded-512";
public static readonly string OQS_SIG_alg_falcon_padded_1024 = "Falcon-padded-1024";
public static readonly string OQS_SIG_alg_sphincs_sha2_128f_simple = "SPHINCS+-SHA2-128f-simple";
public static readonly string OQS_SIG_alg_sphincs_sha2_128s_simple = "SPHINCS+-SHA2-128s-simple";
public static readonly string OQS_SIG_alg_sphincs_sha2_192f_simple = "SPHINCS+-SHA2-192f-simple";
public static readonly string OQS_SIG_alg_sphincs_sha2_192s_simple = "SPHINCS+-SHA2-192s-simple";
public static readonly string OQS_SIG_alg_sphincs_sha2_256f_simple = "SPHINCS+-SHA2-256f-simple";
public static readonly string OQS_SIG_alg_sphincs_sha2_256s_simple = "SPHINCS+-SHA2-256s-simple";
public static readonly string OQS_SIG_alg_sphincs_shake_128f_simple = "SPHINCS+-SHAKE-128f-simple";
public static readonly string OQS_SIG_alg_sphincs_shake_128s_simple = "SPHINCS+-SHAKE-128s-simple";
public static readonly string OQS_SIG_alg_sphincs_shake_192f_simple = "SPHINCS+-SHAKE-192f-simple";
public static readonly string OQS_SIG_alg_sphincs_shake_192s_simple = "SPHINCS+-SHAKE-192s-simple";
public static readonly string OQS_SIG_alg_sphincs_shake_256f_simple = "SPHINCS+-SHAKE-256f-simple";
public static readonly string OQS_SIG_alg_sphincs_shake_256s_simple = "SPHINCS+-SHAKE-256s-simple";
public static readonly string OQS_SIG_alg_mayo_1 = "MAYO-1";
public static readonly string OQS_SIG_alg_mayo_2 = "MAYO-2";
public static readonly string OQS_SIG_alg_mayo_3 = "MAYO-3";
public static readonly string OQS_SIG_alg_mayo_5 = "MAYO-5";
public static readonly string OQS_SIG_alg_cross_rsdp_128_balanced = "cross-rsdp-128-balanced";
public static readonly string OQS_SIG_alg_cross_rsdp_128_fast = "cross-rsdp-128-fast";
public static readonly string OQS_SIG_alg_cross_rsdp_128_small = "cross-rsdp-128-small";
public static readonly string OQS_SIG_alg_cross_rsdp_192_balanced = "cross-rsdp-192-balanced";
public static readonly string OQS_SIG_alg_cross_rsdp_192_fast = "cross-rsdp-192-fast";
public static readonly string OQS_SIG_alg_cross_rsdp_192_small = "cross-rsdp-192-small";
public static readonly string OQS_SIG_alg_cross_rsdp_256_balanced = "cross-rsdp-256-balanced";
public static readonly string OQS_SIG_alg_cross_rsdp_256_fast = "cross-rsdp-256-fast";
public static readonly string OQS_SIG_alg_cross_rsdp_256_small = "cross-rsdp-256-small";
public static readonly string OQS_SIG_alg_cross_rsdpg_128_balanced = "cross-rsdpg-128-balanced";
public static readonly string OQS_SIG_alg_cross_rsdpg_128_fast = "cross-rsdpg-128-fast";
public static readonly string OQS_SIG_alg_cross_rsdpg_128_small = "cross-rsdpg-128-small";
public static readonly string OQS_SIG_alg_cross_rsdpg_192_balanced = "cross-rsdpg-192-balanced";
public static readonly string OQS_SIG_alg_cross_rsdpg_192_fast = "cross-rsdpg-192-fast";
public static readonly string OQS_SIG_alg_cross_rsdpg_192_small = "cross-rsdpg-192-small";
public static readonly string OQS_SIG_alg_cross_rsdpg_256_balanced = "cross-rsdpg-256-balanced";
public static readonly string OQS_SIG_alg_cross_rsdpg_256_fast = "cross-rsdpg-256-fast";
public static readonly string OQS_SIG_alg_cross_rsdpg_256_small = "cross-rsdpg-256-small";
public static readonly string OQS_SIG_alg_uov_ov_Is = "OV-Is";
public static readonly string OQS_SIG_alg_uov_ov_Ip = "OV-Ip";
public static readonly string OQS_SIG_alg_uov_ov_III = "OV-III";
public static readonly string OQS_SIG_alg_uov_ov_V = "OV-V";
public static readonly string OQS_SIG_alg_uov_ov_Is_pkc = "OV-Is-pkc";
public static readonly string OQS_SIG_alg_uov_ov_Ip_pkc = "OV-Ip-pkc";
public static readonly string OQS_SIG_alg_uov_ov_III_pkc = "OV-III-pkc";
public static readonly string OQS_SIG_alg_uov_ov_V_pkc = "OV-V-pkc";
public static readonly string OQS_SIG_alg_uov_ov_Is_pkc_skc = "OV-Is-pkc-skc";
public static readonly string OQS_SIG_alg_uov_ov_Ip_pkc_skc = "OV-Ip-pkc-skc";
public static readonly string OQS_SIG_alg_uov_ov_III_pkc_skc = "OV-III-pkc-skc";
public static readonly string OQS_SIG_alg_uov_ov_V_pkc_skc = "OV-V-pkc-skc";
}
Loading
Loading