Git Product home page Git Product logo

pkcs11test's Introduction

pkcs11Test: A PKCS#11 Test Suite

Warning: Do not run this test suite against a PKCS#11 token that contains real data; some of the tests may erase or permanently lock the token.

This repository holds a test suite for, and is therefore derived from, the RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).

The test suite exercises v2.2 of the PKCS#11 interface, and covers:

  • library management (init.cc)
  • slot and token management (slot.cc)
  • session management (session.cc, login.cc)
  • object management (object.cc)
  • key management (key.cc)
  • symmetric encryption and decryption (cipher.cc)
  • asymmetric encryption and decryption (cipher.cc)
  • signing and verification (sign.cc, hmac.cc)
  • message digesting (digest.cc)
  • dual-function mechanisms (dual.cc)

To build the test program on Linux, just run make. To run the tests against common Linux PKCS#11 implementations:

This is NOT an official Google product.

Additional make options:

  • PKCS11_LONG_SIZE=32 - set CK_LONG/CK_ULONG size to int32_t/uint32_t. Normally set to long int, which is machine/compiler dependent.
  • STRICT_P11=1 - set structures to packed, which tests against fully compliant PKCS11 implementations.

Example:

make PKCS11_LONG_SIZE=32 STRICT_P11=1

Test Options

The test program requires the following command-line parameters to be set:

  • -m libname: Provide the name of the PKCS#11 library to test.
  • -l libpath: Provide the path holding the PKCS#11 library.

There are also several optional command-line parameters:

  • -s slotid: Provide the slot ID that will be used for the tests
  • -v: Generate verbose output.
  • -u pwd: Provide the user PIN/password.
  • -o pwd: Provide the security officer PIN/password.
  • -w cnm: Name of cipher to use for keys being wrapped in key-wrapping tests. One of { 3DES-CBC, 3DES-ECB, AES-CBC , AES-ECB, ARIA-CBC, ARIA-CBC-PAD , ARIA-ECB, CAMELLIA-CBC, CAMELLIA-CBC-PAD , CAMELLIA-ECB, DES-CBC, DES-ECB , IDEA-CBC, IDEA-ECB }
  • -I: Perform token initialization tests. This will wipe the contents of the PKCS#11 token

The test program uses Google Test, and the Google Test command line options are also available. In particular, --gtest_filter=<filter> can be used to run a subset of the tests.

pkcs11test's People

Contributors

bharsaklemukesh975 avatar blukat29 avatar brandonweeks avatar civanahmetyasin avatar daviddrysdale avatar hlipa avatar inorton avatar jasonbking avatar juikim avatar klali avatar metekesler avatar ondergormez avatar rickydoug avatar sirgfm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pkcs11test's Issues

CreateCopyDestroyObject, read only error for CKA_VALUE

// Make another copy but change the value attribute along the way.
CK_OBJECT_HANDLE object3;
CK_BYTE facefeed[] = { 0xFA, 0xCE, 0xFE, 0xED};
CK_ATTRIBUTE attrs3[] = {
{CKA_VALUE, facefeed, sizeof(facefeed)},
};
EXPECT_CKR_OK(g_fns->C_CopyObject(session_, object, attrs3, 1, &object3));

Updating the CKA_VALUE attribute. It says read-only in the standard. Could the testing process here be wrong?

url

EncryptDecryptInitInvalid test uses invalid instead of valid mechanism

On Solaris PKCS11 implementation EncryptDecryptInitInvalid fails because C_EncryptInit/C_DecryptInit CKR_KEY_HANDLE_INVALID test also passes invalid mechanism. Solaris validates mechanism before key.

See diff:

diff --git a/cipher.cc b/cipher.cc
index 42302a9..cee4a11 100644
--- a/cipher.cc
+++ b/cipher.cc
@@ -233,9 +233,9 @@ TEST_P(SecretKeyTest, EncryptDecryptInitInvalid) {
              g_fns->C_DecryptInit(INVALID_SESSION_HANDLE, &mechanism_, key_.handle()));
 
   EXPECT_CKR(CKR_KEY_HANDLE_INVALID,
-             g_fns->C_EncryptInit(session_, &mechanism, INVALID_OBJECT_HANDLE));
+             g_fns->C_EncryptInit(session_, &mechanism_, INVALID_OBJECT_HANDLE));
   EXPECT_CKR(CKR_KEY_HANDLE_INVALID,
-             g_fns->C_DecryptInit(session_, &mechanism, INVALID_OBJECT_HANDLE));
+             g_fns->C_DecryptInit(session_, &mechanism_, INVALID_OBJECT_HANDLE));
 
   CK_RV rv;
   rv = g_fns->C_EncryptInit(session_, NULL_PTR, key_.handle());

Key Wrap Invalid Test not true

1-

EXPECT_CKR_OK(rv);

İf this test returning CKR_OK

why doesn't this key have AES, RSA, DES3

ObjectAttributes k1_attrs = ObjectAttributes();

and has a mechanism not supported in this code

CK_MECHANISM wrap_mechanism = {CKM_DES_ECB, NULL_PTR, 0};

Why you do not use CKM_DES3_ECB or CKM_AES_KEY_WRAP ?

Because ONE DES not supported, I'm getting an error here.
For example, you must see softHSM C_WrapKey function
https://github.com/opendnssec/SoftHSMv2/blob/8f5e4e488fa4c19d56866e27a046680bfc1793d5/src/lib/SoftHSM.cpp#L6302


2-
Im have a eror because this k1_attrs dont have CKA_EXTRACTABLE

SecretKey k1(session_, k1_attrs);

For example, I might get an error when I test in softHSM.
https://github.com/opendnssec/SoftHSMv2/blob/8f5e4e488fa4c19d56866e27a046680bfc1793d5/src/lib/SoftHSM.cpp#L6415

wrong pin set for session - TokenInit

An attempt is made to log in with g_reset_user_pin at line 347 in slot.cc, but the C_Login error is CKR_PIN_INCORRECT because the password is incorrect. This is actually something that should happen. I think EXPECT_CKR(CKR_PIN_INCORRECT, ...) should be expected here, not EXPECT_CKR_OK or the line "g_reset_user_pin = optarg" should be added under line 181in pkcs11test.cc.

ReadOnlySessionTest.WrapUnwrap Test Error in Login phase

I am getting <CKR_PIN_LEN_RANGE> error in C_Login phase of testing process. When I debug and pass the 1111 password, the pin length is 1 and the password is 0.
Note : In the ReadWriteSessionTest.SOLogin Test, I can pass the login phase with the same password.

Allow a range of acceptable return values for some tests?

There are a number of tests that fail against the library I'm testing with slightly different return values. For instance,

EncryptDecryptInitInvalid/5 expects CKR_KEYTYPE_INCONSISTENT

The test calls C_DecryptInit with a RSA mech and a symmetric key.

In this particular case you could equally say the mech is wrong (CKR_MECHANISM_INVALID) or the key is of the wrong type (CKR_KEYTYPE_INCONSISTENT).

The standard doesn't seem to mandate either as preferred.

What do you think?

Test EnumerateMechanisms Fails on EC flags

Based on my reading on the EC mechanisms there are a number of additional flags for the mechanism that need to be provided:
https://www.oasis-open.org/committees/download.php/50389/CKM_ECDSA_FIPS_186_4_v03.pdf

An EC key in Cryptoki contains information about which variety of EC it is suited for. It is
preferable that a Cryptoki library, which can perform EC mechanisms, be capable of performing
operations with the two varieties of EC, however this is not required. The
CK_MECHANISM_INFO structure CKF_EC_F_P flag identifies a Cryptoki library
supporting EC keys over Fp whereas the CKF_EC_F_2M flag identifies a Cryptoki library
supporting EC keys over F2m. A Cryptoki library that can perform EC mechanisms must set
either or both of these flags for each EC mechanism.

In these specifications there are also three representation methods to define the domain
parameters for an EC key. Only the ecParameters and the namedCurve choices are supported
in Cryptoki. The CK_MECHANISM_INFO structure CKF_EC_ECPARAMETERS flag
identifies a Cryptoki library supporting the ecParameters choice whereas the
CKF_EC_NAMEDCURVE flag identifies a Cryptoki library supporting the namedCurve
choice. A Cryptoki library that can perform EC mechanisms must set either or both of these flags
for each EC mechanism.

In these specifications, an EC public key (i.e. EC point Q) or the base point G when the
ecParameters choice is used can be represented as an octet string of the uncompressed form or
the compressed form. The CK_MECHANISM_INFO structure CKF_EC_UNCOMPRESS
flag identifies a Cryptoki library supporting the uncompressed form whereas the
CKF_EC_COMPRESS flag identifies a Cryptoki library supporting the compressed form. A
Cryptoki library that can perform EC mechanisms must set either or both of these flags for each
EC mechanism

Would it be fair to say that for EC mechanisms (CKM_EC_KEY_PAIR_GEN, CKM_ECDSA, CKM_ECDSA_SHA256, CKM_ECDH1_DERIVE, etc) we should expect to see at least one flag from each of the 3 categories listed above and thus the EnumerateMechanisms needs to differentiate between mechanisms that may support elliptic curves?

alternative slot id

Hi, I'm unable to predictably specify a slot id (decimal) on the command line as they are semi-random in my p11 library.

I'd like to specify the slot to be used in a few different ways:

  • zero-offset slot index
  • match the slot description field

Would you be able to accept a pull request?

Use C_Encrypt Instead of C_EncryptUpdate in DecryptUpdateErrors Test Case

According to the latest PKCS#11 Standard;

After calling C_EncryptInit, the application can either call C_Encrypt to encrypt data in a single part; or
call C_EncryptUpdate zero or more times, followed by C_EncryptFinal, to encrypt data in multiple parts.
The encryption operation is active until the application uses a call to C_Encrypt or C_EncryptFinal to
actually obtain the final piece of ciphertext.

In the implementation on SoftHSMv2 C_EncryptUpdate call doesn't finish the encryption operation. So C_EncryptFinal must be called for a further cryptographic operation.

Instead of this, the C_Encrypt method can be used in the DecryptUpdateErrors test case. And this solves the problem.

Camellia and SHA224 mechanisms do not have flags mapping

PKCS11Test.EnumerateSlots fails for Camellia and SHA224 mechanism types because they don't have flags mapping in global.cc:

mechanism[13]=CKM_SHA224_RSA_PKCS CK_MECHANISM_INFO {.ulMinKeySize=256, .ulMaxKeySize=8192, .flags=CKF_SIGN|CKF_VERIFY}
slot.cc:151: Failure
Value of: extra_flags
Actual: 10240
Expected: 0
mechanism[45]=CKM_SHA224 CK_MECHANISM_INFO {.ulMinKeySize=0, .ulMaxKeySize=0, .flags=CKF_DIGEST}
slot.cc:151: Failure
Value of: extra_flags
Actual: 1024
Expected: 0
mechanism[46]=CKM_SHA224_HMAC CK_MECHANISM_INFO {.ulMinKeySize=1, .ulMaxKeySize=64, .flags=CKF_SIGN|CKF_VERIFY}
slot.cc:151: Failure
Value of: extra_flags
Actual: 10240
Expected: 0
mechanism[47]=CKM_SHA224_HMAC_GENERAL CK_MECHANISM_INFO {.ulMinKeySize=1, .ulMaxKeySize=64, .flags=CKF_SIGN|CKF_VERIFY}
slot.cc:151: Failure
Value of: extra_flags
Actual: 10240
Expected: 0
mechanism[64]=CKM_SHA224_KEY_DERIVATION CK_MECHANISM_INFO {.ulMinKeySize=1, .ulMaxKeySize=28, .flags=CKF_DERIVE}
slot.cc:151: Failure
Value of: extra_flags
Actual: 524288
Expected: 0
mechanism[73]=CKM_CAMELLIA_KEY_GEN CK_MECHANISM_INFO {.ulMinKeySize=16, .ulMaxKeySize=32, .flags=CKF_GENERATE}
slot.cc:151: Failure
Value of: extra_flags
Actual: 32768
Expected: 0
mechanism[74]=CKM_CAMELLIA_ECB CK_MECHANISM_INFO {.ulMinKeySize=16, .ulMaxKeySize=32, .flags=CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}
slot.cc:151: Failure
Value of: extra_flags
Actual: 393984
Expected: 0
mechanism[75]=CKM_CAMELLIA_CBC CK_MECHANISM_INFO {.ulMinKeySize=16, .ulMaxKeySize=32, .flags=CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}
slot.cc:151: Failure
Value of: extra_flags
Actual: 393984
Expected: 0
mechanism[76]=CKM_CAMELLIA_CBC_PAD CK_MECHANISM_INFO {.ulMinKeySize=16, .ulMaxKeySize=32, .flags=CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}
slot.cc:151: Failure
Value of: extra_flags
Actual: 393984
Expected: 0
mechanism[77]=CKM_CAMELLIA_CTR CK_MECHANISM_INFO {.ulMinKeySize=16, .ulMaxKeySize=32, .flags=CKF_ENCRYPT|CKF_DECRYPT|CKF_WRAP|CKF_UNWRAP}
slot.cc:151: Failure
Value of: extra_flags
Actual: 393984
Expected: 0

CreateCopyDestroyObject, read only error for CKA_VALUE

Updating the CKA_VALUE attribute. It says read-only in the standard. Could the testing process here be wrong?

// Make another copy but change the value attribute along the way.
CK_OBJECT_HANDLE object3;
CK_BYTE facefeed[] = { 0xFA, 0xCE, 0xFE, 0xED};
CK_ATTRIBUTE attrs3[] = {
{CKA_VALUE, facefeed, sizeof(facefeed)},
};
EXPECT_CKR_OK(g_fns->C_CopyObject(session_, object, attrs3, 1, &object3));

#53 (comment)

VENDOR_DEFINED values are not processed correctly

All vendor defined values like CKM_VENDOR_DEFINED are minimal not exact value. Standard says:

[Mechanism types CKM_VENDOR_DEFINED and above are permanently reserved for token vendors.]

but in mechanism_type_name() we can see:

case CKR_VENDOR_DEFINED: return "CKR_VENDOR_DEFINED";

instead of:

if (val >= CKM_VENDOR_DEFINED) return "CKM_VENDOR_DEFINED";

It finally leads to situation when function returns "UNKNOWN" instead of "CKM_VENDOR_DEFINED" string.

ReadOnlySessionTest.SeedRandom should allow CKR_RANDOM_SEED_NOT_SUPPORTED

Currently, if an RNG is present, the ReadOnlySessionTest.SeedRandom test is preformed where the RNG is seeded with a constant known value. I cannot find any text in the current PKCS#11 spec that requires an RNG to support explicit seeding. That would imply the test should not fail when CKR_RANDOM_SEED_NOT_SUPPORTED is returned.

WrapUnwrap - Wrong key type set used

Incorrect key type assigned in test. DES3 object was created but wrong type was given in UnwrapKey operation.

key.cc - Line : 137
-CK_KEY_TYPE key_type = CKK_DES;
+CK_KEY_TYPE key_type = CKK_DES3;

The EnumerateMechanisms test fails with vendor defined / unknown mechs

The PKCS#11 library I'm testing with (nCipher PKCS#11) supports a large number of vendor-defined mechs.

The EnumerateMechanisms test wrongly checks these mechs for unexpected mech flags and fails.

If a mech is unknown to the test suite we should skip checking it's allowed flags values.

pointer passed into pReserved of CK_C_INITIALIZE_ARGS passed to C_Initialize

Hi there,

I've just ran your test suite and have found it passes a value in the reserved member of the C_Initialize args.

The library I'm testing with makes use of this reserved pointer if set for internal testing data (perhaps it shouldn't) and the test makes the library segfault.

What is the expected behaviour for a well formed library? Can I easily turn this off?

ReadOnlySessionTest.WrapUnwrap - Expected wrong return value

"ReadOnlySessionTest.WrapUnwrap" In this test case, it is requested to create a Private Key during R / W Public operation. It is written that this operation should not be allowed in the section "2.6.4 Permitted object accesses by sessions". Therefore, the transaction cannot be expected to be successful here. The return value of the function should be "CKR_USER_NOT_LOGGED_IN" but the expected value is "CKR_OK". Could there be a bug in this testing process?

2.6.4 Permitted object accesses by sessions

OUTPUT:

key.cc:145: Failure
Value of: CK_RV_((g_fns->C_UnwrapKey(session_, &wrap_mechanism, k2.handle(), data, data_len, k3_attrs, 5, &k3)))
  Actual: CKR_USER_NOT_LOGGED_IN
Expected: CK_RV_(0x00000000)
Which is: CKR_OK

Improper function calls in FindObject tests

EXPECT_CKR_OK(g_fns->C_FindObjects(session_, object, sizeof(object), &count));

EXPECT_CKR_OK(g_fns->C_FindObjects(session_, object, sizeof(object), &count));

EXPECT_CKR_OK(g_fns->C_FindObjects(session_, object, sizeof(object), &count));

g_fns->C_FindObjects(session_, object, sizeof(object), &count));

g_fns->C_FindObjects(INVALID_SESSION_HANDLE, object, sizeof(object), &count));

g_fns->C_FindObjects(session_, object, sizeof(object), NULL_PTR));

g_fns->C_FindObjects(session_, object, sizeof(object), &count));

By PKCS#11 specification,

ulMaxObjectCount is the maximum number of object handles to be returned

So, I think the value of third parameter should be capacity of object variable(in this case, 5), not a octet count of object variable.

Issue in CreateKeyPair Test

File: keypair.cc
Test: TEST_F(ReadWriteSessionTest, CreateKeyPairObjects)

While populating the data for private key template, improper use of stack variables.

if (!keydata.prime1.empty()) {
string data = hex_decode(keydata.prime1);
private_attrs.push_back({CKA_PRIME_1, (CK_BYTE_PTR)data.data(), prime1.size()});
}

-- data variable goes out of scope once we exit if condition

This is applicable for other attributes as well - prime2, exponent1, exponent2, coefficient

Regards,
Praveen

WrapUnwrap - attribute set is missing

key.cc - Line:138
CKA_EXTRACTABLE must be explicitly specified as true for the new object.

CK_ATTRIBUTE k3_attrs[] = {
    {CKA_LABEL, (CK_VOID_PTR)g_label, g_label_len},
    {CKA_CLASS, &key_class, sizeof(key_class)},
    {CKA_KEY_TYPE, (CK_VOID_PTR)&key_type, sizeof(key_type)},
    {CKA_ENCRYPT, (CK_VOID_PTR)&g_ck_true, sizeof(CK_BBOOL)},
    {CKA_DECRYPT, (CK_VOID_PTR)&g_ck_true, sizeof(CK_BBOOL)},
+  {CKA_EXTRACTABLE, (CK_VOID_PTR)&g_ck_true, sizeof(CK_BBOOL)},
    };

Clarification related to InitToken Tests

In slot.cc, TEST_F(PKCS11Test, TokenInit),

After C_InitToken() call with g_so_pin , there is a comment which says "both the pins would have been reset. we need to set them back". But as per PKCS#11 v2.40 doc, it says the value of SO Pin at the end of C_InitToken() call shall be that of pPin which is passed as an argument to the call. In our case it will be g_so_pin and NOT g_reset_so_pin.

Improper function calls in FindObject tests

EXPECT_CKR_OK(g_fns->C_FindObjects(session_, object, sizeof(object), &count));

EXPECT_CKR_OK(g_fns->C_FindObjects(session_, object, sizeof(object), &count));

EXPECT_CKR_OK(g_fns->C_FindObjects(session_, object, sizeof(object), &count));

g_fns->C_FindObjects(session_, object, sizeof(object), &count));

g_fns->C_FindObjects(INVALID_SESSION_HANDLE, object, sizeof(object), &count));

g_fns->C_FindObjects(session_, object, sizeof(object), NULL_PTR));

g_fns->C_FindObjects(session_, object, sizeof(object), &count));

By PKCS#11 specification,

ulMaxObjectCount is the maximum number of object handles to be returned

So, I think the value of third parameter should be capacity of object variable(in this case, 5), not a octet count of object variable.

Wrong value set in keypair.cc

Wrong value set for recoveryed_plaintext_len in keypair.cc (line:120)

CK_BYTE recovered_plaintext[1024];
-CK_ULONG recovered_plaintext_len = sizeof(plaintext);
rv = g_fns->C_Decrypt(session_, ciphertext, ciphertext_len, recovered_plaintext, &recovered_plaintext_len);

+CK_ULONG recovered_plaintext_len = sizeof(recovered_plaintext);

Incorrect skip message

If the imported library does not support some sign/verify mechanisms, the following messages are displayed.

Following tests were skipped because: Digest type CKM_MD5_HMAC not implemented
  HMACs/HmacTest.SignVerify/0
  HMACs/HmacTest.SignFailVerify/0
Following tests were skipped because: Digest type CKM_MD5_RSA_PKCS not implemented
  Signatures/SignTest.SignVerify/1
  Signatures/SignTest.SignFailVerifyWrong/1
  Signatures/SignTest.SignFailVerifyShort/1
Following tests were skipped because: Digest type CKM_SHA1_RSA_PKCS not implemented
  Signatures/SignTest.SignVerify/2
  Signatures/SignTest.SignFailVerifyWrong/2
  Signatures/SignTest.SignFailVerifyShort/2
Following tests were skipped because: Digest type CKM_SHA256_HMAC not implemented
  HMACs/HmacTest.SignVerify/2
  HMACs/HmacTest.SignFailVerify/2
Following tests were skipped because: Digest type CKM_SHA256_RSA_PKCS not implemented
  Signatures/SignTest.SignVerify/3
  Signatures/SignTest.SignFailVerifyWrong/3
  Signatures/SignTest.SignFailVerifyShort/3
Following tests were skipped because: Digest type CKM_SHA384_HMAC not implemented
  HMACs/HmacTest.SignVerify/3
  HMACs/HmacTest.SignFailVerify/3
Following tests were skipped because: Digest type CKM_SHA384_RSA_PKCS not implemented
  Signatures/SignTest.SignVerify/4
  Signatures/SignTest.SignFailVerifyWrong/4
  Signatures/SignTest.SignFailVerifyShort/4
Following tests were skipped because: Digest type CKM_SHA512_HMAC not implemented
  HMACs/HmacTest.SignVerify/4
  HMACs/HmacTest.SignFailVerify/4
Following tests were skipped because: Digest type CKM_SHA512_RSA_PKCS not implemented
  Signatures/SignTest.SignVerify/5
  Signatures/SignTest.SignFailVerifyWrong/5
  Signatures/SignTest.SignFailVerifyShort/5
Following tests were skipped because: Digest type CKM_SHA_1_HMAC not implemented
  HMACs/HmacTest.SignVerify/1
  HMACs/HmacTest.SignFailVerify/1

According to the message, the test was skipped because Digest was not supported. However, the test was skipped because Sign was not actually supported.

This message may confuse to anyone testing the library (at least I did). Therefore, it is suggested to change the part noted Digest in the message to Sign.

Related codes that need to be changed are as follows.

ss << "Digest type " << mechanism_type_name(mechanism_.mechanism) << " not implemented"; \

ss << "Digest type " << mechanism_type_name(mechanism_.mechanism) << " not implemented"; \

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.