yebin-yu / openssh_with_ukey

Other
0 stars 0 forks source link

UKEY签名代码 #13

Closed yebin-yu closed 6 months ago

yebin-yu commented 6 months ago
void SM2_gmSig2OpensslSig(ECCSIGNATUREBLOB *sigBlob, unsigned char **sig, size_t *len)
{
    BIGNUM *rB=NULL;
    BIGNUM *sB=NULL;

    BYTE *r = sigBlob->r+32;
    BYTE *s = sigBlob->s+32;

    rB = BN_bin2bn(r, 32, NULL);
    if(rB == NULL) {return NULL;}
    sB = BN_bin2bn(s, 32, NULL);
    if(sB == NULL) {return NULL;}

    ECDSA_SIG *ecdsaSig = ECDSA_SIG_new();
    if (ecdsaSig == NULL) {return NULL;}

    if(ECDSA_SIG_set0(ecdsaSig, rB, sB) != 1) {
        return NULL;
    }

    unsigned char* sig_temp = NULL;
    int sigLen = i2d_ECDSA_SIG(ecdsaSig, sig);
    // *sig = sig_temp;
    printf("%s", *sig);
    *len = sigLen;
}

static int
init_ukey_container(HCONTAINER *hcontainer)
{
    HANDLE hdev = NULL;
    ULONG ulRslt = SAR_OK;

    // 枚举获取设备名,这里的逻辑应该是自动获取然后赋值
    // ukey上获取到的值应该为:3DC2105010CFD4C62A42E5375DA38B9
    char szDevName[256] = {0}; 
    ULONG ulDevNameLen = 256;
    ulRslt = SKF_EnumDev(TRUE, szDevName, &ulDevNameLen);
    printf("szDevName: %s \n", szDevName);
    if (ulRslt != SAR_OK) {
        debug("SKF_EnumDev ERROR \n");
        return 1;
    }

    // 连接设备
    ulRslt = SKF_ConnectDev(szDevName, &hdev);
    if (ulRslt != SAR_OK) {
        debug("SKF_ConnectDev ERROR \n");
        return 1;
    }

    // 获取application,这里的逻辑应该是自动获取然后赋值
    // ukey上获取到的值应该为:GM3000RSA
    char appName[256] = {0}; 
    ULONG appnameLen = 256;
    ulRslt = SKF_EnumApplication(hdev, appName, &appnameLen);
    printf("appName: %s\n", appName);
    if (ulRslt != SAR_OK) {
        debug("SKF_EnumApplication ERROR \n");
        return 1;
    }

    // 打开应用
    HANDLE happ;
    ulRslt = SKF_OpenApplication(hdev, appName, &happ);
    if (ulRslt != SAR_OK) {
        debug("SKF_OpenApplication ERROR \n");
        return 1;
    }

    // 验证pin码
    char pinStr[32];
    ULONG retryCntMax = 3;
    ULONG currentRetryCnt = 0;
    printf("UKEY pin:");
    scanf("%s", pinStr);
    ulRslt = SKF_VerifyPIN(happ, USER_TYPE, pinStr, &retryCntMax);
    while (ulRslt != SAR_OK && currentRetryCnt++ < retryCntMax) {
        sleep(2);  // 防止暴力破解,等待两秒
        printf("UKEY pin again:");
        scanf("%s", pinStr);
        ulRslt = SKF_VerifyPIN(happ, USER_TYPE, pinStr, &retryCntMax);
    }
    if (ulRslt != SAR_OK) {
        debug("SKF_VerifyPIN ERROR \n");
        return 1;
    }

    // 获取容器名
    // ukey上获取到的值应该为:sm2
    char containerName[256] = {0};
    ULONG containerNameLen = 256;
    ulRslt = SKF_EnumContainer(happ, containerName, &containerNameLen);
    printf("containerName: %s\n", containerName);
    if (ulRslt != SAR_OK) {
        debug("SKF_EnumContainer ERROR \n");
        return 1;
    }

    // 打开容器
    ulRslt = SKF_OpenContainer(happ, containerName, hcontainer);
    if (ulRslt != SAR_OK) {
        debug("SKF_OpenContainer ERROR \n");
        return 1;
    }

    return SAR_OK;
}

static int
ukey_get_sig(const u_char *data, size_t datalen, u_char **sig, size_t *slen, struct sshkey *sign_key)
{   
    // get container handle
    ULONG ulRslt = SAR_OK;
    HCONTAINER container = NULL;
    if (init_ukey_container(&container) != 0) {
        debug("init_ukey_container ERROR \n");
        return 1;
    }

    // hash
    unsigned char hashRslt[32] = {0};
    int hashLen;
    if(1 != EVP_Digest(data, datalen, hashRslt, &hashLen, EVP_sm3(), NULL, sign_key)) {
        debug("EVP_Digest ERROR \n");
        return 1;
    }

    // sign
    ECCSIGNATUREBLOB stSign = {0};
    ulRslt = SKF_ECCSignData(container, hashRslt, hashLen, &stSign);
    if (ulRslt != SAR_OK) {
        debug("SKF_ECCSignData ERROR \n");
        return 1;
    }

    SM2_gmSig2OpensslSig(&stSign, sig, slen);
    return 0;
}

其中 EVP_Digest 为:

int EVP_Digest(const void *data, size_t count,
               unsigned char *md, unsigned int *size, const EVP_MD *type,
               ENGINE *impl, struct sshkey *sign_key)
{

    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    int ret;
    EVP_PKEY *key_sm2 = NULL;

    if ((key_sm2 = EVP_PKEY_new()) == NULL) {
        return SSH_ERR_ALLOC_FAIL;
    }

    if ((EVP_PKEY_set1_EC_KEY(key_sm2, sign_key->ecdsa)) != 1) {
        ret = SSH_ERR_INTERNAL_ERROR;
        return 0;
    }

    if (ctx == NULL)
        return 0;
    EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT);
    ret = EVP_DigestInit_ex(ctx, type, impl)
        && EVP_DigestUpdate(ctx, data, count)
        && EVP_DigestFinal_ex(ctx, md, size);
    EVP_MD_CTX_free(ctx);

    return ret;
}