• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Cryptographic Algorithm Functions
2
3openHiTLS provides functions such as encryption and decryption, signature verification, and hash calculation based on the cryptographic algorithm standard. Provided by algorithm module, the main function interfaces support the default cryptographic algorithm capability for the certificate and TLS module in the openHiTLS system
4
5## Function Specifications
6
7* Encryption and decryption: supports symmetric encryption and decryption based on SM4, AES, and CHACHA20, and asymmetric encryption and decryption based on SM2 and RSA.
8* Signature verification: supports SM2, DSA, ED25519, RSA, and ECDSA.
9* Key exchange: supports SM2, X25519, and ECDH.
10* Key derivation: supports PBKDF2, HKDF, SCRYPT, and KDFTLS12.
11* Integrity algorithm: supports integrity protection based on HMAC.
12* Hash calculation: supports digest calculation based on SM3, SHA2, SHA3, MD5, and SHA1.
13* Random number generation: supports DRBG-HASH, DRBG-CTR, and DRBG-HMAC.
14
15# Examples of Encryption and Decryption
16
17## Symmetric Encryption and Decryption
18
19This function provides encryption and decryption capabilities based on symmetric algorithms. The following uses the SM4-CBC algorithm as an example to describe the sample code for reference.
20
21## Sample Code
22
23```c
24#include <stdio.h>
25#include <stdlib.h>
26#include <stdint.h>
27#include <string.h>
28#include "crypt_eal_cipher.h" // Header file of the interfaces for symmetric encryption and decryption.
29#include "bsl_sal.h"
30#include "bsl_err.h"
31#include "crypt_algid.h" // Algorithm ID list.
32#include "crypt_errno.h" // Error code list.
33
34void *StdMalloc(uint32_t len) {
35    return malloc((size_t)len);
36}
37
38void PrintLastError(void) {
39    const char *file = NULL;
40    uint32_t line = 0;
41    BSL_ERR_GetLastErrorFileLine(&file, &line); // Obtain the name and number of lines of the error file.
42    printf("failed at file %s at line %d\n", file, line);
43}
44
45int main(void)
46{
47    uint8_t data[10] = {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x1c, 0x14};
48    uint8_t iv[16] = {0};
49    uint8_t key[16] = {0};
50    uint32_t dataLen = sizeof(data);
51    uint8_t cipherText[100];
52    uint8_t plainText[100];
53    uint32_t outTotalLen = 0;
54    uint32_t outLen = sizeof(cipherText);
55    uint32_t cipherTextLen;
56    int32_t ret;
57
58    printf("plain text to be encrypted: ");
59    for (uint32_t i = 0; i < dataLen; i++) {
60        printf("%02x", data[i]);
61    }
62    printf("\n");
63
64    // Initialize the error code module.
65    BSL_ERR_Init();
66
67    // Before calling the algorithm APIs, call the **BSL_SAL_CallBack_Ctrl** function to register the **malloc** and **free** functions. Execute this step only once.
68    // If the memory allocation ability of Linux is available, the two functions can be registered using Linux by default.
69    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_MALLOC, StdMalloc);
70    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_FREE, free);
71
72    // Create a context.
73    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_CipherNewCtx(CRYPT_CIPHER_SM4_CBC);
74    if (ctx == NULL) {
75        PrintLastError();
76        BSL_ERR_DeInit();
77        return 1;
78    }
79    // During initialization, the last input parameter can be **true** or **false**. **true** indicates encryption, and **false** indicates decryption.
80    ret = CRYPT_EAL_CipherInit(ctx, key, sizeof(key), iv, sizeof(iv), true);
81    if (ret != CRYPT_SUCCESS) {
82        printf("error code is %x\n", ret); // Output the error code. You can find the error information in **crypt_errno.h** based on the error code.
83        PrintLastError();
84        goto EXIT;
85    }
86    // Set the padding mode.
87    ret = CRYPT_EAL_CipherSetPadding(ctx, CRYPT_PADDING_PKCS7);
88    if (ret != CRYPT_SUCCESS) {
89        printf("error code is %x\n", ret);
90        PrintLastError();
91        goto EXIT;
92    }
93
94    // Enter the data to be calculated. This interface can be called for multiple times. The input value of **outLen** is the length of the ciphertext, and the output value is the amount of processed data.
95    ret = CRYPT_EAL_CipherUpdate(ctx, data, dataLen, cipherText, &outLen);
96    if (ret != CRYPT_SUCCESS) {
97        printf("error code is %x\n", ret);
98        PrintLastError();
99        goto EXIT;
100    }
101
102    outTotalLen += outLen;
103    outLen = sizeof(cipherText) - outTotalLen;
104
105    ret = CRYPT_EAL_CipherFinal(ctx, cipherText + outTotalLen, &outLen);
106    if (ret != CRYPT_SUCCESS) {
107        printf("error code is %x\n", ret);
108        PrintLastError();
109        goto EXIT;
110    }
111
112    outTotalLen += outLen;
113    printf("cipher text value is: ");
114
115    for (uint32_t i = 0; i < outTotalLen; i++) {
116        printf("%02x", cipherText[i]);
117    }
118    printf("\n");
119
120    // Start decryption.
121    cipherTextLen = outTotalLen;
122    outTotalLen = 0;
123    outLen = sizeof(plainText);
124
125    // When initializing the decryption function, set the last input parameter to **false**.
126    ret = CRYPT_EAL_CipherInit(ctx, key, sizeof(key), iv, sizeof(iv), false);
127    if (ret != CRYPT_SUCCESS) {
128        printf("error code is %x\n", ret);
129        PrintLastError();
130        goto EXIT;
131    }
132
133    //Set the padding mode, which must be the same as that for encryption.
134    ret = CRYPT_EAL_CipherSetPadding(ctx, CRYPT_PADDING_PKCS7);
135    if (ret != CRYPT_SUCCESS) {
136        printf("error code is %x\n", ret);
137        PrintLastError();
138        goto EXIT;
139    }
140
141    // Enter the ciphertext data.
142    ret = CRYPT_EAL_CipherUpdate(ctx, cipherText, cipherTextLen, plainText, &outLen);
143    if (ret != CRYPT_SUCCESS) {
144        printf("error code is %x\n", ret);
145        PrintLastError();
146        goto EXIT;
147    }
148    outTotalLen += outLen;
149    outLen = sizeof(plainText) - outTotalLen;
150
151    // Decrypt the last segment of data and remove the filled content.
152    ret = CRYPT_EAL_CipherFinal(ctx, plainText + outTotalLen, &outLen);
153    if (ret != CRYPT_SUCCESS) {
154        printf("error code is %x\n", ret);
155        PrintLastError();
156        goto EXIT;
157    }
158
159    outTotalLen += outLen;
160
161    printf("decrypted plain text value is: ");
162    for (uint32_t i = 0; i < outTotalLen; i++) {
163        printf("%02x", plainText[i]);
164    }
165    printf("\n");
166
167    if (outTotalLen != dataLen || memcmp(plainText, data, dataLen) != 0) {
168        printf("plaintext comparison failed\n");
169        goto EXIT;
170    }
171    printf("pass \n");
172
173EXIT:
174    CRYPT_EAL_CipherFreeCtx(ctx);
175    BSL_ERR_DeInit();
176    return ret;
177}
178```
179
180## Asymmetric Encryption and Decryption
181
182This function provides encryption and decryption capabilities based on asymmetric algorithms. The following uses the SM2 encryption and decryption process as an example to describe the sample code for reference.
183
184## Sample Code
185
186```c
187#include <stdio.h>
188#include <stdlib.h>
189#include <stdint.h>
190#include <string.h>
191#include "crypt_eal_pkey.h" // Header file of the interfaces for asymmetric encryption and decryption.
192#include "bsl_sal.h"
193#include "bsl_err.h"
194#include "crypt_algid.h"
195#include "crypt_errno.h"
196#include "crypt_eal_rand.h"
197#include "crypt_eal_init.h"
198#include "crypt_types.h"
199
200void *StdMalloc(uint32_t len) {
201    return malloc((uint32_t)len);
202}
203void PrintLastError(void) {
204    const char *file = NULL;
205    uint32_t line = 0;
206    BSL_ERR_GetLastErrorFileLine(&file, &line);
207    printf("failed at file %s at line %d\n", file, line);
208}
209
210int main(void) {
211    int32_t ret;
212    BSL_ERR_Init();  // Initialize the error code module.
213    // Before calling the algorithm APIs, call the **BSL_SAL_CallBack_Ctrl** function to register the **malloc** and **free** functions. Execute this step only once.
214    // If the memory allocation ability of Linux is available, the two functions can be registered using Linux by default.
215    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_MALLOC, StdMalloc);
216    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_FREE, free);
217    ret = CRYPT_EAL_Init(CRYPT_EAL_INIT_CPU | CRYPT_EAL_INIT_PROVIDER);
218    if (ret != CRYPT_SUCCESS) {
219        printf("error code is %x\n", ret);
220        PrintLastError();
221        goto EXIT;
222    }
223    CRYPT_EAL_PkeyCtx *pkey = NULL;
224    pkey = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_SM2);
225    if (pkey == NULL) {
226        PrintLastError();
227        goto EXIT;
228    }
229
230    // Initialize the random number.
231    ret = CRYPT_EAL_ProviderRandInitCtx(NULL, CRYPT_RAND_SHA256, "provider=default", NULL, 0, NULL);
232    if (ret != CRYPT_SUCCESS) {
233        printf("CRYPT_EAL_RandInit: error code is %x\n", ret);
234        PrintLastError();
235        goto EXIT;
236    }
237
238    // Generate a key pair.
239    ret = CRYPT_EAL_PkeyGen(pkey);
240    if (ret != CRYPT_SUCCESS) {
241        printf("CRYPT_EAL_PkeyGen: error code is %x\n", ret);
242        PrintLastError();
243        goto EXIT;
244    }
245
246    // Data to be encrypted.
247    char *data = "test enc data";
248    uint32_t dataLen = 12;
249    uint8_t ecrypt[125] = {0};
250    uint32_t ecryptLen = 125;
251    uint8_t dcrypt[125] = {0};
252    uint32_t dcryptLen = 125;
253    // Encrypt data.
254    ret = CRYPT_EAL_PkeyEncrypt(pkey, data, dataLen, ecrypt, &ecryptLen);
255    if (ret != CRYPT_SUCCESS) {
256        printf("CRYPT_EAL_PkeyEncrypt: error code is %x\n", ret);
257        PrintLastError();
258        goto EXIT;
259    }
260
261    // Decrypt data.
262    ret = CRYPT_EAL_PkeyDecrypt(pkey, ecrypt, ecryptLen, dcrypt, &dcryptLen);
263    if (ret != CRYPT_SUCCESS) {
264        printf("CRYPT_EAL_PkeyDecrypt: error code is %x\n", ret);
265        PrintLastError();
266        goto EXIT;
267    }
268
269    if (memcmp(dcrypt, data, dataLen) == 0) {
270        printf("encrypt and decrypt success\n");
271    } else {
272        ret = -1;
273    }
274EXIT:
275    // Release the context memory.
276    CRYPT_EAL_PkeyFreeCtx(pkey);
277    CRYPT_EAL_RandDeinit();
278    BSL_ERR_DeInit();
279    return ret;
280}
281```
282
283# Example of Signature Verification
284
285## Algorithm Type
286
287This function provides the signature verification capability based on asymmetric algorithms. The following uses SM2 signature verification as an example to describe the sample code for reference.
288
289## Sample Code
290
291```c
292#include <stdio.h>
293#include <stdlib.h>
294#include <stdint.h>
295#include <string.h>
296#include "crypt_eal_pkey.h" // Header file for signature verification.
297#include "bsl_sal.h"
298#include "bsl_err.h"
299#include "crypt_algid.h"
300#include "crypt_errno.h"
301#include "crypt_eal_init.h"
302#include "crypt_eal_rand.h"
303
304void *StdMalloc(uint32_t len) {
305    return malloc((size_t)len);
306}
307
308void PrintLastError(void) {
309    const char *file = NULL;
310    uint32_t line = 0;
311    BSL_ERR_GetLastErrorFileLine(&file, &line);// Obtain the name and number of lines of the error file.
312    printf("failed at file %s at line %d\n", file, line);
313}
314
315int main(void)
316{
317    int ret;
318    uint8_t userId[32] = {0};
319    uint8_t key[32] = {0};
320    uint8_t msg[32] = {0};
321    uint8_t signBuf[100] = {0};
322    uint32_t signLen = sizeof(signBuf);
323    CRYPT_EAL_PkeyPrv prv = {0};
324    CRYPT_EAL_PkeyPub pub = {0};
325    CRYPT_EAL_PkeyCtx *ctx = NULL;
326
327    BSL_ERR_Init(); // Initialize the error code module.
328    // Before calling the algorithm APIs, call the **BSL_SAL_CallBack_Ctrl** function to register the **malloc** and **free** functions. Execute this step only once.
329    // If the memory allocation ability of Linux is available, the two functions can be registered using Linux by default.
330    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_MALLOC, StdMalloc);
331    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_FREE, free);
332    ret = CRYPT_EAL_Init(CRYPT_EAL_INIT_CPU | CRYPT_EAL_INIT_PROVIDER);
333    if (ret != CRYPT_SUCCESS) {
334        goto EXIT;
335    }
336    ctx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_SM2);
337    if (ctx == NULL) {
338        goto EXIT;
339    }
340
341    // Set a user ID.
342    ret = CRYPT_EAL_PkeyCtrl(ctx, CRYPT_CTRL_SET_SM2_USER_ID, userId, sizeof(userId));
343    if (ret != CRYPT_SUCCESS) {
344        printf("error code is %x\n", ret);
345        PrintLastError();
346        goto EXIT;
347    }
348
349    // Initialize the random number.
350    ret = CRYPT_EAL_ProviderRandInitCtx(NULL, CRYPT_RAND_SHA256, "provider=default", NULL, 0, NULL);
351    if (ret != CRYPT_SUCCESS) {
352        printf("error code is %x\n", ret);
353        PrintLastError();
354        goto EXIT;
355    }
356
357    // Generate a key pair.
358    ret = CRYPT_EAL_PkeyGen(ctx);
359    if (ret != CRYPT_SUCCESS) {
360        printf("error code is %x\n", ret);
361        PrintLastError();
362        goto EXIT;
363    }
364
365    // Sign.
366    ret = CRYPT_EAL_PkeySign(ctx, CRYPT_MD_SM3, msg, sizeof(msg), signBuf, &signLen);
367    if (ret != CRYPT_SUCCESS) {
368        printf("error code is %x\n", ret);
369        PrintLastError();
370        goto EXIT;
371    }
372
373    // Verify the signature.
374    ret = CRYPT_EAL_PkeyVerify(ctx, CRYPT_MD_SM3, msg, sizeof(msg), signBuf, signLen);
375    if (ret != CRYPT_SUCCESS) {
376        printf("error code is %x\n", ret);
377        PrintLastError();
378        goto EXIT;
379    }
380
381    printf("pass \n");
382
383EXIT:
384    // Release the context memory.
385    CRYPT_EAL_PkeyFreeCtx(ctx);
386    CRYPT_EAL_RandDeinit();
387    BSL_ERR_DeInit();
388    return ret;
389}
390```
391
392# Example of Key Exchange
393
394## Algorithm Type
395
396This function provides the key exchange capability based on asymmetric algorithms. The following uses ECDH as an example to describe the sample code for reference.
397
398## Sample Code
399
400```c
401#include <stdio.h>
402#include <stdlib.h>
403#include <stdint.h>
404#include <string.h>
405#include "crypt_types.h"
406#include "crypt_eal_pkey.h" // Header file for key exchange.
407#include "bsl_sal.h"
408#include "bsl_err.h"
409#include "crypt_algid.h"
410#include "crypt_errno.h"
411#include "crypt_eal_rand.h"
412#include "crypt_eal_init.h"
413
414void *StdMalloc(uint32_t len) {
415    return malloc((size_t)len);
416}
417
418void PrintLastError(void) {
419    const char *file = NULL;
420    uint32_t line = 0;
421    BSL_ERR_GetLastErrorFileLine(&file, &line);
422    printf("failed at file %s at line %d\n", file, line);
423}
424
425int main(void)
426{
427    int ret;
428
429    uint8_t prikey[] =
430        {0x7d, 0x7d, 0xc5, 0xf7, 0x1e, 0xb2, 0x9d, 0xda, 0xf8, 0x0d, 0x62, 0x14, 0x63, 0x2e, 0xea, 0xe0,
431         0x3d, 0x90, 0x58, 0xaf, 0x1f, 0xb6, 0xd2, 0x2e, 0xd8, 0x0b, 0xad, 0xb6, 0x2b, 0xc1, 0xa5, 0x34};
432    uint8_t pubkey[] =
433        {0x04, 0x70, 0x0c, 0x48, 0xf7, 0x7f, 0x56, 0x58, 0x4c, 0x5c, 0xc6, 0x32, 0xca, 0x65, 0x64, 0x0d, 0xb9,
434         0x1b, 0x6b, 0xac, 0xce, 0x3a, 0x4d, 0xf6, 0xb4, 0x2c, 0xe7, 0xcc, 0x83, 0x88, 0x33, 0xd2, 0x87,
435         0xdb, 0x71, 0xe5, 0x09, 0xe3, 0xfd, 0x9b, 0x06, 0x0d, 0xdb, 0x20, 0xba, 0x5c, 0x51, 0xdc, 0xc5,
436         0x94, 0x8d, 0x46, 0xfb, 0xf6, 0x40, 0xdf, 0xe0, 0x44, 0x17, 0x82, 0xca, 0xb8, 0x5f, 0xa4, 0xac};
437    uint8_t resSharekey[] =
438        {0x46, 0xfc, 0x62, 0x10, 0x64, 0x20, 0xff, 0x01, 0x2e, 0x54, 0xa4, 0x34, 0xfb, 0xdd, 0x2d, 0x25,
439         0xcc, 0xc5, 0x85, 0x20, 0x60, 0x56, 0x1e, 0x68, 0x04, 0x0d, 0xd7, 0x77, 0x89, 0x97, 0xbd, 0x7b};
440
441    CRYPT_EAL_PkeyPrv prvKey = {0};
442    CRYPT_EAL_PkeyPub pubKey = {0};
443    uint32_t shareLen;
444    uint8_t *shareKey;
445    CRYPT_EAL_PkeyCtx *prvCtx = NULL;
446    CRYPT_EAL_PkeyCtx *pubCtx = NULL;
447    CRYPT_PKEY_ParaId id = CRYPT_ECC_NISTP256;
448
449    BSL_ERR_Init(); // Initialize the error code module.
450    // Before calling the algorithm APIs, call the **BSL_SAL_CallBack_Ctrl** function to register the **malloc** and **free** functions. Execute this step only once.
451    // If the memory allocation ability of Linux is available, the two functions can be registered using Linux by default.
452    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_MALLOC, StdMalloc);
453    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_FREE, free);
454    ret = CRYPT_EAL_Init(CRYPT_EAL_INIT_CPU | CRYPT_EAL_INIT_PROVIDER);
455    if (ret != CRYPT_SUCCESS) {
456        printf("error code is %x\n", ret);
457        goto EXIT;
458    }
459    prvCtx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_ECDH);
460    pubCtx = CRYPT_EAL_PkeyNewCtx(CRYPT_PKEY_ECDH);
461    if (prvCtx == NULL || pubCtx == NULL) {
462        goto EXIT;
463    }
464
465    // Set the curve parameters.
466    ret = CRYPT_EAL_PkeySetParaById(prvCtx, id);
467    if (ret != CRYPT_SUCCESS) {
468        printf("error code is %x\n", ret);
469        PrintLastError();
470        goto EXIT;
471    }
472
473    // Set the private key of one end.
474    prvKey.id = CRYPT_PKEY_ECDH;
475    prvKey.key.eccPrv.len = sizeof(prikey);
476    prvKey.key.eccPrv.data = prikey;
477    ret = CRYPT_EAL_PkeySetPrv(prvCtx, &prvKey);
478    if (ret != CRYPT_SUCCESS) {
479        printf("error code is %x\n", ret);
480        PrintLastError();
481        goto EXIT;
482    }
483
484    // Set the curve parameters.
485    ret = CRYPT_EAL_PkeySetParaById(pubCtx, id);
486    if (ret != CRYPT_SUCCESS) {
487        printf("error code is %x\n", ret);
488        PrintLastError();
489        goto EXIT;
490    }
491
492    // Set the public key of the other end.
493    pubKey.id = CRYPT_PKEY_ECDH;
494    pubKey.key.eccPub.len = sizeof(pubkey);
495    pubKey.key.eccPub.data = pubkey;
496    ret = CRYPT_EAL_PkeySetPub(pubCtx, &pubKey);
497    if (ret != CRYPT_SUCCESS) {
498        printf("error code is %x\n", ret);
499        PrintLastError();
500        goto EXIT;
501    }
502
503    // The shared key involves only the X axis. The length of the public key is not compressed in the returned results.
504    shareLen = CRYPT_EAL_PkeyGetKeyLen(prvCtx) / 2;
505    shareKey = (uint8_t *)BSL_SAL_Malloc(shareLen);
506    if (shareKey == NULL) {
507        ret = CRYPT_MEM_ALLOC_FAIL;
508        PrintLastError();
509        goto EXIT;
510    }
511
512    // Initialize the random number.
513    ret = CRYPT_EAL_ProviderRandInitCtx(NULL, CRYPT_RAND_SHA256, "provider=default", NULL, 0, NULL);
514    if (ret != CRYPT_SUCCESS) {
515        printf("CRYPT_EAL_RandInit: error code is %x\n", ret);
516        PrintLastError();
517        goto EXIT;
518    }
519
520    // Calculate the shared key.
521    ret = CRYPT_EAL_PkeyComputeShareKey(prvCtx, pubCtx, shareKey, &shareLen);
522    if (ret != CRYPT_SUCCESS) {
523        printf("error code is %x\n", ret);
524        PrintLastError();
525        goto EXIT;
526    }
527
528    // Compare the calculation result with the expected one.
529    if (shareLen != sizeof(resSharekey) || memcmp(shareKey, resSharekey, shareLen) != 0) {
530        printf("failed to compare test results\n");
531        ret = -1;
532        goto EXIT;
533    }
534
535    printf("pass \n");
536
537EXIT:
538    // Release the context memory.
539    CRYPT_EAL_RandDeinit();
540    CRYPT_EAL_PkeyFreeCtx(prvCtx);
541    CRYPT_EAL_PkeyFreeCtx(pubCtx);
542    BSL_SAL_Free(shareKey);
543    BSL_ERR_DeInit();
544    return 0;
545}
546```
547
548# Example of Key Derivation
549
550## Algorithm Type
551
552The PBKDF2, HKDF, SCRYPT, and KDFTLS12 algorithms can be used for key derivation. The following uses PBKDF2 as an example to describe the sample code for reference.
553
554## Sample Code
555
556```c
557#include <stdint.h>
558#include <stdlib.h>
559#include <stdio.h>
560#include <string.h>
561#include "crypt_errno.h"
562#include "bsl_sal.h"
563#include "bsl_err.h"
564#include "crypt_algid.h"
565#include "crypt_eal_kdf.h"
566#include "bsl_params.h"
567#include "crypt_params_key.h"
568
569#define PBKDF2_PARAM_LEN (4)
570
571void *StdMalloc(uint32_t len) {
572    return malloc((size_t)len);
573}
574
575void PrintLastError(void) {
576    const char *file = NULL;
577    uint32_t line = 0;
578    BSL_ERR_GetLastErrorFileLine(&file, &line);
579    printf("failed at file %s at line %d\n", file, line);
580}
581
582int main(void)
583{
584    int32_t ret;
585    uint8_t key[] = {0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64};
586    uint8_t salt[] = {0x4e, 0x61, 0x43, 0x6c};
587    uint32_t iterations = 80000;
588    uint8_t result[] = {
589        0x4d, 0xdc, 0xd8, 0xf6, 0x0b, 0x98, 0xbe, 0x21,
590        0x83, 0x0c, 0xee, 0x5e, 0xf2, 0x27, 0x01, 0xf9,
591        0x64, 0x1a, 0x44, 0x18, 0xd0, 0x4c, 0x04, 0x14,
592        0xae, 0xff, 0x08, 0x87, 0x6b, 0x34, 0xab, 0x56,
593        0xa1, 0xd4, 0x25, 0xa1, 0x22, 0x58, 0x33, 0x54,
594        0x9a, 0xdb, 0x84, 0x1b, 0x51, 0xc9, 0xb3, 0x17,
595        0x6a, 0x27, 0x2b, 0xde, 0xbb, 0xa1, 0xd0, 0x78,
596        0x47, 0x8f, 0x62, 0xb3, 0x97, 0xf3, 0x3c, 0x8d};
597
598    uint8_t out[sizeof(result)] = {0};
599    uint32_t outLen = sizeof(result);
600
601    // Initialize the error code module.
602    BSL_ERR_Init();
603
604    /**
605     * Before calling the algorithm APIs,
606     * call the BSL_SAL_CallBack_Ctrl function to register the malloc and free functions.
607     * Execute this step only once. If the memory allocation ability of Linux is available,
608     * the two functions can be registered using Linux by default.
609    */
610    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_MALLOC, StdMalloc);
611    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_FREE, free);
612
613    CRYPT_EAL_KdfCTX *ctx = CRYPT_EAL_KdfNewCtx(CRYPT_KDF_PBKDF2);
614    if (ctx == NULL) {
615        PrintLastError();
616        goto EXIT;
617    }
618    CRYPT_MAC_AlgId id = CRYPT_MAC_HMAC_SHA256;
619    BSL_Param params[5] = {{0}, {0}, {0}, {0}, BSL_PARAM_END};
620    (void)BSL_PARAM_InitValue(&params[0], CRYPT_PARAM_KDF_MAC_ID, BSL_PARAM_TYPE_UINT32, &id, sizeof(id));
621    (void)BSL_PARAM_InitValue(&params[1], CRYPT_PARAM_KDF_PASSWORD, BSL_PARAM_TYPE_OCTETS, key, sizeof(key));
622    (void)BSL_PARAM_InitValue(&params[2], CRYPT_PARAM_KDF_SALT, BSL_PARAM_TYPE_OCTETS, salt, sizeof(salt));
623    (void)BSL_PARAM_InitValue(&params[3], CRYPT_PARAM_KDF_ITER, BSL_PARAM_TYPE_UINT32, &iterations, sizeof(iterations));
624    ret = CRYPT_EAL_KdfSetParam(ctx, params);
625    if (ret != CRYPT_SUCCESS) {
626        printf("error code is %x\n", ret);
627        PrintLastError();
628        goto EXIT;
629    }
630
631    ret = CRYPT_EAL_KdfDerive(ctx, out, outLen);
632    if (ret != CRYPT_SUCCESS) {
633        printf("error code is %x\n", ret);
634        PrintLastError();
635        goto EXIT;
636    }
637
638    if (memcmp(out, result, sizeof(result)) != 0) {
639        printf("failed to compare test results\n");
640        ret = -1;
641        goto EXIT;
642    }
643    printf("pass \n");
644
645EXIT:
646    BSL_ERR_DeInit();
647    CRYPT_EAL_KdfFreeCtx(ctx);
648    return ret;
649}
650```
651
652# Example of Random Number Generation
653
654## Algorithm Type
655
656The DRBG-SHA, DRBG-HMAC, and DRBG-CTR algorithms can be used for random number generation. The interfaces include global random number interfaces and multi-instance random number interfaces.
657
658```c
659/*
660*  Global random number initializing and deinitializing interfaces.
661 * The **seedMeth** value of initializing interfaces is the entropy source of the callback, and the **seedCtx** value is the context called back by the user.
662*  Users can set their own entropy source. If it is not set, the default entropy source is used.
663*  Currently, entropy can be obtained from **/dev/random** of Linux.
664*/
665int32_t CRYPT_EAL_RandInit(CRYPT_RAND_AlgId id, CRYPT_RandSeedMethod *seedMeth, void *seedCtx, const uint8_t *pers, uint32_t persLen);
666void CRYPT_EAL_RandDeinit(void);
667
668/* After initialization, users can call the following interfaces to obtain the pseudo-random number and supplement the entropy source.*/
669int32_t CRYPT_EAL_Randbytes(uint8_t *byte, uint32_t len);
670int32_t CRYPT_EAL_RandSeed(void);
671
672/*The deterministic random bit generator (DRBG) context of the multi-instance random number interfaces is returned to the user. This is the main difference between the two types of interfaces.
673 * Multiple DRBG contexts can be created. Different contexts do not interfere with each other during entropy source setting and internal status change.*/
674CRYPT_EAL_RndCtx *CRYPT_EAL_DrbgNew(CRYPT_RAND_AlgId id, CRYPT_RandSeedMethod *seedMeth, void *seedCtx);
675void CRYPT_EAL_DrbgDeinit(CRYPT_EAL_RndCtx *ctx);
676```
677
678The following uses the DRBG-SHA algorithm as an example to describe the sample code for reference.
679
680## Sample Code
681
682```c
683#include <stdio.h>
684#include <stdlib.h>
685#include <stdint.h>
686#include <string.h>
687#include "crypt_types.h"
688#include "bsl_sal.h"
689#include "bsl_err.h"
690#include "crypt_algid.h"
691#include "crypt_errno.h"
692#include "crypt_eal_init.h"
693#include "crypt_eal_rand.h"
694
695void *StdMalloc(uint32_t len) {
696    return malloc((size_t)len);
697}
698
699void PrintLastError(void) {
700    const char *file = NULL;
701    uint32_t line = 0;
702    BSL_ERR_GetLastErrorFileLine(&file, &line);
703    printf("failed at file %s at line %d\n", file, line);
704}
705
706int main(void)
707{
708    int ret;
709    uint8_t output[100] = {0};
710    uint32_t len = 100;
711
712    // Before calling the algorithm APIs, call the **BSL_SAL_CallBack_Ctrl** function to register the **malloc** and **free** functions. Execute this step only once.
713    // If the memory allocation ability of Linux is available, the two functions can be registered using Linux by default.
714    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_MALLOC, StdMalloc);
715    BSL_SAL_CallBack_Ctrl(BSL_SAL_MEM_FREE, free);
716
717    BSL_ERR_Init();// Initialize the error module.
718    ret = CRYPT_EAL_Init(CRYPT_EAL_INIT_CPU | CRYPT_EAL_INIT_PROVIDER);
719    if (ret != CRYPT_SUCCESS) {
720        printf("error code is %x\n", ret);
721        goto EXIT;
722    }
723    // Initialize the global random number by using the default entropy source from **/dev/random** of Linux.
724    ret = CRYPT_EAL_ProviderRandInitCtx(NULL, CRYPT_RAND_SHA256, "provider=default", NULL, 0, NULL);
725    if (ret != CRYPT_SUCCESS) {
726        printf("CRYPT_EAL_RandInit: error code is %x\n", ret);
727        PrintLastError();
728        goto EXIT;
729    }
730
731    // Obtain the random number sequence of the **len** value.
732    ret = CRYPT_EAL_RandbytesEx(NULL, output, len);
733    if (ret != CRYPT_SUCCESS) {
734        printf("CRYPT_EAL_Randbytes: error code is %x\n", ret);
735        PrintLastError();
736        goto EXIT;
737    }
738
739    printf("random value is: ");  // Output the random number.
740    for (uint32_t i = 0; i < len; i++) {
741        printf("%02x", output[i]);
742    }
743    printf("\n");
744
745    // Reseeding
746    ret = CRYPT_EAL_RandSeedEx(NULL);
747    if (ret != CRYPT_SUCCESS) {
748        printf("CRYPT_EAL_RandSeed: error code is %x\n", ret);
749        PrintLastError();
750        goto EXIT;
751    }
752
753    // Obtain the random number sequence of the **len** value.
754    ret = CRYPT_EAL_RandbytesEx(NULL, output, len);
755    if (ret != CRYPT_SUCCESS) {
756        printf("CRYPT_EAL_Randbytes: error code is %x\n", ret);
757        PrintLastError();
758        goto EXIT;
759    }
760
761    printf("random value is: "); // Output the random number.
762    for (uint32_t i = 0; i < len; i++) {
763        printf("%02x", output[i]);
764    }
765    printf("\n");
766
767EXIT:
768    // Release the context memory.
769    CRYPT_EAL_RandDeinit();
770    BSL_ERR_DeInit();
771    return 0;
772}
773```
774