SYS_STATUS RxHDCP_GenVR(BYTE Vr[]) { // extern void SHA_Simple(void *p, LONG len, BYTE *output); int i, n ; n = cDownStream*5+10 ; for(i = n ; i < 64 ; i++) { SHABuff[i] = 0 ; } for(i = 0 ; i < 64 ; i++) { HDMIRX_DEBUG_PRINTF2(("%02X ",(int)SHABuff[i])); if(0==((i+1)%8))HDMIRX_DEBUG_PRINTF2(("\n")); } HDMIRX_DEBUG_PRINTF(("n=%2X\n",(int)n)); SHA_Simple(SHABuff, (LONG)n, Vr); HDMIRX_DEBUG_PRINTF2(("SHA[]: ")); for(i = 0 ; i < 20 ; i++) { HDMIRX_DEBUG_PRINTF2(("%02X ",(int)Vr[i])); } HDMIRX_DEBUG_PRINTF2(("\n")); return ER_SUCCESS ; }
void RSAKey::Sign( const CString &data, CString &out ) const { Bignum in; { unsigned char hash[20]; SHA_Simple(data.data(), data.size(), hash); int nbytes = (bignum_bitcount(this->modulus) - 1) / 8; unsigned char *bytes = new unsigned char[nbytes]; memset( bytes, 0xFF, nbytes ); bytes[0] = 1; memcpy( bytes + nbytes - 20, hash, 20 ); in = bignum_from_bytes(bytes, nbytes); delete [] bytes; } Bignum outnum = rsa_privkey_op(in, this); delete [] in; int siglen; unsigned char *bytes = bignum_to_bytes( outnum, &siglen ); delete [] outnum; out = CString( (const char *) bytes, siglen ); delete [] bytes; }
static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) { struct dss_key *dss = (struct dss_key *) key; Bignum k, gkp, hash, kinv, hxr, r, s; unsigned char digest[20]; unsigned char *bytes; int nbytes, i; SHA_Simple(data, datalen, digest); k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x, digest, sizeof(digest)); kinv = modinv(k, dss->q); /* k^-1 mod q */ assert(kinv); /* * Now we have k, so just go ahead and compute the signature. */ gkp = modpow(dss->g, k, dss->p); /* g^k mod p */ r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */ freebn(gkp); hash = bignum_from_bytes(digest, 20); hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */ s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */ freebn(hxr); freebn(kinv); freebn(k); freebn(hash); /* * Signature blob is * * string "ssh-dss" * string two 20-byte numbers r and s, end to end * * i.e. 4+7 + 4+40 bytes. */ nbytes = 4 + 7 + 4 + 40; bytes = snewn(nbytes, unsigned char); PUT_32BIT(bytes, 7); memcpy(bytes + 4, "ssh-dss", 7); PUT_32BIT(bytes + 4 + 7, 40); for (i = 0; i < 20; i++) { bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i); bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i); } freebn(r); freebn(s); *siglen = nbytes; return bytes; }
static int rsa2_verifysig(void *key, char *sig, int siglen, char *data, int datalen) { struct RSAKey *rsa = (struct RSAKey *) key; Bignum in, out; char *p; int slen; int bytes, i, j, ret; unsigned char hash[20]; getstring(&sig, &siglen, &p, &slen); if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) { return 0; } in = getmp(&sig, &siglen); out = modpow(in, rsa->exponent, rsa->modulus); freebn(in); ret = 1; bytes = (bignum_bitcount(rsa->modulus)+7) / 8; /* Top (partial) byte should be zero. */ if (bignum_byte(out, bytes - 1) != 0) ret = 0; /* First whole byte should be 1. */ if (bignum_byte(out, bytes - 2) != 1) ret = 0; /* Most of the rest should be FF. */ for (i = bytes - 3; i >= 20 + ASN1_LEN; i--) { if (bignum_byte(out, i) != 0xFF) ret = 0; } /* Then we expect to see the asn1_weird_stuff. */ for (i = 20 + ASN1_LEN - 1, j = 0; i >= 20; i--, j++) { if (bignum_byte(out, i) != asn1_weird_stuff[j]) ret = 0; } /* Finally, we expect to see the SHA-1 hash of the signed data. */ SHA_Simple(data, datalen, hash); for (i = 19, j = 0; i >= 0; i--, j++) { if (bignum_byte(out, i) != hash[j]) ret = 0; } freebn(out); return ret; }
static unsigned char *rsa2_sign(void *key, char *data, int datalen, int *siglen) { struct RSAKey *rsa = (struct RSAKey *) key; unsigned char *bytes; int nbytes; unsigned char hash[20]; Bignum in, out; int i, j; SHA_Simple(data, datalen, hash); nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8; assert(1 <= nbytes - 20 - ASN1_LEN); bytes = snewn(nbytes, unsigned char); bytes[0] = 1; for (i = 1; i < nbytes - 20 - ASN1_LEN; i++) bytes[i] = 0xFF; for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++) bytes[i] = asn1_weird_stuff[j]; for (i = nbytes - 20, j = 0; i < nbytes; i++, j++) bytes[i] = hash[j]; in = bignum_from_bytes(bytes, nbytes); sfree(bytes); out = rsa_privkey_op(in, rsa); freebn(in); nbytes = (bignum_bitcount(out) + 7) / 8; bytes = snewn(4 + 7 + 4 + nbytes, unsigned char); PUT_32BIT(bytes, 7); memcpy(bytes + 4, "ssh-rsa", 7); PUT_32BIT(bytes + 4 + 7, nbytes); for (i = 0; i < nbytes; i++) bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i); freebn(out); *siglen = 4 + 7 + 4 + nbytes; return bytes; }
bool RSAKey::Verify( const CString &data, const CString &sig ) const { Bignum in, out; int bytes, i, j; unsigned char hash[20]; in = bignum_from_bytes( (const unsigned char *) sig.data(), sig.size() ); /* Base (in) must be smaller than the modulus. */ if( bignum_cmp(in, this->modulus) >= 0 ) { freebn(in); return false; } out = modpow(in, this->exponent, this->modulus); freebn(in); bool ret = true; bytes = (bignum_bitcount(this->modulus)+7) / 8; /* Top (partial) byte should be zero. */ if (bignum_byte(out, bytes - 1) != 0) ret = 0; /* First whole byte should be 1. */ if (bignum_byte(out, bytes - 2) != 1) ret = 0; /* Most of the rest should be FF. */ for (i = bytes - 3; i >= 20; i--) { if (bignum_byte(out, i) != 0xFF) ret = 0; } /* Finally, we expect to see the SHA-1 hash of the signed data. */ SHA_Simple( data.data(), data.size(), hash ); for (i = 19, j = 0; i >= 0; i--, j++) { if (bignum_byte(out, i) != hash[j]) ret = false; } freebn(out); return ret; }
static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) { /* * The basic DSS signing algorithm is: * * - invent a random k between 1 and q-1 (exclusive). * - Compute r = (g^k mod p) mod q. * - Compute s = k^-1 * (hash + x*r) mod q. * * This has the dangerous properties that: * * - if an attacker in possession of the public key _and_ the * signature (for example, the host you just authenticated * to) can guess your k, he can reverse the computation of s * and work out x = r^-1 * (s*k - hash) mod q. That is, he * can deduce the private half of your key, and masquerade * as you for as long as the key is still valid. * * - since r is a function purely of k and the public key, if * the attacker only has a _range of possibilities_ for k * it's easy for him to work through them all and check each * one against r; he'll never be unsure of whether he's got * the right one. * * - if you ever sign two different hashes with the same k, it * will be immediately obvious because the two signatures * will have the same r, and moreover an attacker in * possession of both signatures (and the public key of * course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q, * and from there deduce x as before. * * - the Bleichenbacher attack on DSA makes use of methods of * generating k which are significantly non-uniformly * distributed; in particular, generating a 160-bit random * number and reducing it mod q is right out. * * For this reason we must be pretty careful about how we * generate our k. Since this code runs on Windows, with no * particularly good system entropy sources, we can't trust our * RNG itself to produce properly unpredictable data. Hence, we * use a totally different scheme instead. * * What we do is to take a SHA-512 (_big_) hash of the private * key x, and then feed this into another SHA-512 hash that * also includes the message hash being signed. That is: * * proto_k = SHA512 ( SHA512(x) || SHA160(message) ) * * This number is 512 bits long, so reducing it mod q won't be * noticeably non-uniform. So * * k = proto_k mod q * * This has the interesting property that it's _deterministic_: * signing the same hash twice with the same key yields the * same signature. * * Despite this determinism, it's still not predictable to an * attacker, because in order to repeat the SHA-512 * construction that created it, the attacker would have to * know the private key value x - and by assumption he doesn't, * because if he knew that he wouldn't be attacking k! * * (This trick doesn't, _per se_, protect against reuse of k. * Reuse of k is left to chance; all it does is prevent * _excessively high_ chances of reuse of k due to entropy * problems.) * * Thanks to Colin Plumb for the general idea of using x to * ensure k is hard to guess, and to the Cambridge University * Computer Security Group for helping to argue out all the * fine details. */ struct dss_key *dss = (struct dss_key *) key; SHA512_State ss; unsigned char digest[20], digest512[64]; Bignum proto_k, k, gkp, hash, kinv, hxr, r, s; unsigned char *bytes; int nbytes, i; SHA_Simple(data, datalen, digest); /* * Hash some identifying text plus x. */ SHA512_Init(&ss); SHA512_Bytes(&ss, "DSA deterministic k generator", 30); sha512_mpint(&ss, dss->x); SHA512_Final(&ss, digest512); /* * Now hash that digest plus the message hash. */ SHA512_Init(&ss); SHA512_Bytes(&ss, digest512, sizeof(digest512)); SHA512_Bytes(&ss, digest, sizeof(digest)); SHA512_Final(&ss, digest512); memset(&ss, 0, sizeof(ss)); /* * Now convert the result into a bignum, and reduce it mod q. */ proto_k = bignum_from_bytes(digest512, 64); k = bigmod(proto_k, dss->q); freebn(proto_k); memset(digest512, 0, sizeof(digest512)); /* * Now we have k, so just go ahead and compute the signature. */ gkp = modpow(dss->g, k, dss->p); /* g^k mod p */ r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */ freebn(gkp); hash = bignum_from_bytes(digest, 20); kinv = modinv(k, dss->q); /* k^-1 mod q */ hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */ s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */ freebn(hxr); freebn(kinv); freebn(hash); /* * Signature blob is * * string "ssh-dss" * string two 20-byte numbers r and s, end to end * * i.e. 4+7 + 4+40 bytes. */ nbytes = 4 + 7 + 4 + 40; bytes = snewn(nbytes, unsigned char); PUT_32BIT(bytes, 7); memcpy(bytes + 4, "ssh-dss", 7); PUT_32BIT(bytes + 4 + 7, 40); for (i = 0; i < 20; i++) { bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i); bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i); } freebn(r); freebn(s); *siglen = nbytes; return bytes; }
static int dss_verifysig(void *key, char *sig, int siglen, char *data, int datalen) { struct dss_key *dss = (struct dss_key *) key; char *p; int slen; char hash[20]; Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v; int ret; if (!dss->p) return 0; #ifdef DEBUG_DSS { int i; printf("sig:"); for (i = 0; i < siglen; i++) printf(" %02x", (unsigned char) (sig[i])); printf("\n"); } #endif /* * Commercial SSH (2.0.13) and OpenSSH disagree over the format * of a DSA signature. OpenSSH is in line with the IETF drafts: * it uses a string "ssh-dss", followed by a 40-byte string * containing two 160-bit integers end-to-end. Commercial SSH * can't be bothered with the header bit, and considers a DSA * signature blob to be _just_ the 40-byte string containing * the two 160-bit integers. We tell them apart by measuring * the length: length 40 means the commercial-SSH bug, anything * else is assumed to be IETF-compliant. */ if (siglen != 40) { /* bug not present; read admin fields */ getstring(&sig, &siglen, &p, &slen); if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) { return 0; } sig += 4, siglen -= 4; /* skip yet another length field */ } r = get160(&sig, &siglen); s = get160(&sig, &siglen); if (!r || !s) return 0; /* * Step 1. w <- s^-1 mod q. */ w = modinv(s, dss->q); /* * Step 2. u1 <- SHA(message) * w mod q. */ SHA_Simple(data, datalen, (unsigned char *)hash); p = hash; slen = 20; sha = get160(&p, &slen); u1 = modmul(sha, w, dss->q); /* * Step 3. u2 <- r * w mod q. */ u2 = modmul(r, w, dss->q); /* * Step 4. v <- (g^u1 * y^u2 mod p) mod q. */ gu1p = modpow(dss->g, u1, dss->p); yu2p = modpow(dss->y, u2, dss->p); gu1yu2p = modmul(gu1p, yu2p, dss->p); v = modmul(gu1yu2p, One, dss->q); /* * Step 5. v should now be equal to r. */ ret = !bignum_cmp(v, r); freebn(w); freebn(sha); freebn(gu1p); freebn(yu2p); freebn(gu1yu2p); freebn(v); freebn(r); freebn(s); return ret; }
static int LAME_ssh2_load_userkey(char *passphrase) { int passlen = strlen(passphrase); unsigned char out[sizeof(cur_salt->private_blob)]; AES_KEY akey; unsigned char iv[32]; /* Decrypt the private blob. */ if (cur_salt->cipher) { unsigned char key[40]; SHA_CTX s; if (cur_salt->private_blob_len % cur_salt->cipherblk) goto error; SHA1_Init(&s); SHA1_Update(&s, (void*)"\0\0\0\0", 4); SHA1_Update(&s, passphrase, passlen); SHA1_Final(key + 0, &s); SHA1_Init(&s); SHA1_Update(&s, (void*)"\0\0\0\1", 4); SHA1_Update(&s, passphrase, passlen); SHA1_Final(key + 20, &s); memset(iv, 0, 32); memset(&akey, 0, sizeof(AES_KEY)); if(AES_set_decrypt_key(key, 256, &akey) < 0) { fprintf(stderr, "AES_set_decrypt_key failed!\n"); } AES_cbc_encrypt(cur_salt->private_blob, out , cur_salt->private_blob_len, &akey, iv, AES_DECRYPT); } /* Verify the MAC. */ { char realmac[41]; unsigned char binary[20]; unsigned char *macdata; unsigned char macdata_ar[4*5+sizeof(cur_salt->alg)+sizeof(cur_salt->encryption)+sizeof(cur_salt->comment)+sizeof(cur_salt->public_blob_len)+sizeof(cur_salt->private_blob_len)+1]; int maclen; int i; if (cur_salt->old_fmt) { /* MAC (or hash) only covers the private blob. */ macdata = out; maclen = cur_salt->private_blob_len; } else { unsigned char *p; int namelen = strlen(cur_salt->alg); int enclen = strlen(cur_salt->encryption); int commlen = strlen(cur_salt->comment); maclen = (4 + namelen + 4 + enclen + 4 + commlen + 4 + cur_salt->public_blob_len + 4 + cur_salt->private_blob_len); p = macdata_ar; #define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len) DO_STR(cur_salt->alg, namelen); DO_STR(cur_salt->encryption, enclen); DO_STR(cur_salt->comment, commlen); DO_STR(cur_salt->public_blob, cur_salt->public_blob_len); DO_STR(out, cur_salt->private_blob_len); macdata = macdata_ar; } if (cur_salt->is_mac) { SHA_CTX s; unsigned char mackey[20]; unsigned int length = 20; // HMAC_CTX ctx; char header[] = "putty-private-key-file-mac-key"; SHA1_Init(&s); SHA1_Update(&s, header, sizeof(header)-1); if (cur_salt->cipher && passphrase) SHA_Update(&s, passphrase, passlen); SHA1_Final(mackey, &s); hmac_sha1(mackey, 20, macdata, maclen, binary, length); /* HMAC_Init(&ctx, mackey, 20, EVP_sha1()); * HMAC_Update(&ctx, macdata, maclen); * HMAC_Final(&ctx, binary, &length); * HMAC_CTX_cleanup(&ctx); */ } else { SHA_Simple(macdata, maclen, binary); } for (i = 0; i < 20; i++) sprintf(realmac + 2 * i, "%02x", binary[i]); if (strcmp(cur_salt->mac, realmac) == 0) return 1; } error: return 0; }
unsigned char *sc_sig(void *f, int try_write_syslog, sc_lib *sclib, const char *token_label, const char *password_s, char *sigdata, int sigdata_len, int *sigblob_len) { CK_RV rv = 0; char msg[SC_STR_MAX_LEN] = ""; CK_SESSION_HANDLE session = 0; const char *pwd = password_s; /* TEMPLATES: */ CK_BBOOL bTrue = 1; CK_OBJECT_CLASS class_private_key = CKO_PRIVATE_KEY; CK_KEY_TYPE key_type = CKK_RSA; CK_ATTRIBUTE key_template[] = { { CKA_CLASS, &class_private_key, sizeof (class_private_key) }, { CKA_KEY_TYPE, &key_type, sizeof (key_type) }, { CKA_TOKEN, &bTrue, sizeof (bTrue) }, { CKA_SIGN, &bTrue, sizeof (bTrue) }, { CKA_PRIVATE, &bTrue, sizeof (bTrue) } }; CK_ATTRIBUTE key_getattributes[] = { {CKA_ID, NULL_PTR, 0}, /* ID to search the key */ {CKA_MODULUS, NULL_PTR, 0} }; /* STORE OBJECTS AND ATTRIBUTES */ int max_o = 20; CK_OBJECT_HANDLE list[max_o]; CK_ULONG found = 0; CK_OBJECT_HANDLE pO; int ii,j; unsigned char *ret = NULL; *sigblob_len = 0; session = sc_get_session(f, try_write_syslog, sclib->m_fl, token_label); if(session == 0) { return NULL; } rv = sclib->m_fl->C_Login(session, CKU_USER, (CK_CHAR_PTR)pwd, strlen(pwd)); if (CKR_OK != rv) { logevent(f, "sc: Login failed"); sclib->m_fl->C_CloseSession(session); return NULL; } rv = sclib->m_fl->C_FindObjectsInit(session, key_template, 4); if (CKR_OK != rv) { sprintf(msg, "sc: C_FindObjectsInit priv key failed, 0x%.4x", (int)rv); goto err; } rv = sclib->m_fl->C_FindObjects(session, list, max_o-1, &found); if (CKR_OK != rv) { sprintf(msg, "sc: C_FindObjects priv key failed, 0x%.4x", (int)rv); goto err; } rv = sclib->m_fl->C_FindObjectsFinal(session); if (CKR_OK != rv) { sprintf(msg, "sc: C_FindObjectsFinal priv key failed, 0x%.4x", (int)rv); goto err; } if (found < 1) { sprintf(msg, "sc: No priv keys found"); goto err; } for(ii=0; ii<found; ii++) { pO = list[ii]; int ts = 1;//sizeof (key_getattributes) / sizeof (CK_ATTRIBUTE); int nr; sc_write_syslog("1"); for(nr=0;nr<ts;nr++) { key_getattributes[nr].ulValueLen = 0; key_getattributes[nr].pValue = NULL; } rv = sclib->m_fl->C_GetAttributeValue(session, pO, key_getattributes, ts); if(CKR_OK == rv) { for(nr=0;nr<ts;nr++) { key_getattributes[nr].pValue = calloc(sizeof(char *),key_getattributes[nr].ulValueLen+1); } if(sclib->m_fl->C_GetAttributeValue(session, pO, key_getattributes, ts) == CKR_OK) { if(strncmp(key_getattributes[0].pValue, sclib->m_KeyID, key_getattributes[0].ulValueLen) == 0) { CK_BYTE signature[500]; CK_ULONG signature_length = 500; CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 }; unsigned char *bytes; Bignum out; int nbytes; int r; unsigned char hash_sha[20]; char p_buf[key_getattributes[0].ulValueLen+1]; memset(p_buf, 0, key_getattributes[0].ulValueLen+1); strncpy(p_buf, key_getattributes[0].pValue, key_getattributes[0].ulValueLen); sprintf(msg, "sc: Found pkey: %s", p_buf); logevent(f, msg); if(try_write_syslog) sc_write_syslog(msg); rv = sclib->m_fl->C_SignInit(session, &mechanism, pO); if (CKR_OK != rv) { free(key_getattributes[0].pValue); free(key_getattributes[1].pValue); sprintf(msg, "sc: SignInit failed, 0x%.4x", (int)rv); goto err; } /* rsa2_sign() */ SHA_Simple(sigdata, sigdata_len, hash_sha); // MD5Simple(sigdata, sigdata_len, hash_md5); { int message_len = sizeof(id_sha1) + sizeof(hash_sha); CK_BYTE message[message_len]; for(j=0;j<sizeof(id_sha1);j++) message[j] = id_sha1[j]; memcpy((char *) &message[sizeof(id_sha1)], hash_sha, sizeof(hash_sha)); rv = sclib->m_fl->C_Sign(session, message, message_len, signature, &signature_length); if (CKR_OK != rv) { free(key_getattributes[0].pValue); free(key_getattributes[1].pValue); sprintf(msg, "sc: Sign failed, 0x%.4x", (int)rv); goto err; } } out = bignum_from_bytes(signature, signature_length); nbytes = (bignum_bitcount(out) + 7) / 8; *sigblob_len = 4 + 7 + 4 + nbytes; bytes = calloc(sizeof(char *), *sigblob_len); SC_PUT_32BIT(bytes, 7); memcpy(bytes + 4, "ssh-rsa", 7); SC_PUT_32BIT(bytes + 4 + 7, nbytes); for (r = 0; r < nbytes; r++) bytes[4 + 7 + 4 + r] = bignum_byte(out, nbytes - 1 - r); ret = bytes; free(out); free(key_getattributes[0].pValue); free(key_getattributes[1].pValue); break; } } else { logevent(f, "sc: GetAttributeValue failed, no data loaded"); } free(key_getattributes[0].pValue); free(key_getattributes[1].pValue); } else { sprintf(msg, "sc: GetAttributeValue failed (pkey), 0x%.4x", (int)rv); logevent(f, msg); if(try_write_syslog) sc_write_syslog(msg); } } sclib->m_fl->C_Logout(session); sclib->m_fl->C_CloseSession(session); return ret; err: logevent(f, msg); if(try_write_syslog) sc_write_syslog(msg); sclib->m_fl->C_Logout(session); sclib->m_fl->C_CloseSession(session); if(ret != NULL) free(ret); /* just return an invalid signature ... */ *sigblob_len = 1; return " "; }