/* * Compute a SHA checksum on the username, cellname, and password */ void weblog_login_checksum(char *user, char *cell, char *passwd, char *cksum) { int passwdLen; int userLen; int cellLen; char *shaBuffer; shaState state; /* * Compute SHA(username,SHA(password,pad)) */ passwdLen = strlen(passwd); userLen = strlen(user); cellLen = strlen(cell); shaBuffer = (char *)malloc(MAX(userLen + cellLen, passwdLen) + SHA_HASH_BYTES); strcpy(shaBuffer, passwd); memcpy((void *)(shaBuffer + passwdLen), (void *)(&weblog_login_pad[0]), SHA_HASH_BYTES); sha_clear(&state); sha_hash(&state, shaBuffer, passwdLen + SHA_HASH_BYTES); memcpy(shaBuffer, user, userLen); memcpy(shaBuffer + userLen, cell, cellLen); sha_bytes(&state, shaBuffer + userLen + cellLen); sha_clear(&state); sha_hash(&state, shaBuffer, userLen + cellLen + SHA_HASH_BYTES); sha_bytes(&state, &cksum[0]); memset(shaBuffer, 0, MAX(userLen + cellLen, passwdLen) + SHA_HASH_BYTES); free(shaBuffer); }
/* note that this call terminates the key input phase */ void hmac_sha_data(const unsigned char data[], unsigned long data_len, hmac_ctx cx[1]) { unsigned int i; if(cx->klen != HMAC_IN_DATA) /* if not yet in data phase */ { if(cx->klen > HASH_INPUT_SIZE) /* if key is being hashed */ { /* complete the hash and */ sha_end(cx->key, cx->ctx); /* store the result as the */ cx->klen = HASH_OUTPUT_SIZE; /* key and set new length */ } /* pad the key if necessary */ memset(cx->key + cx->klen, 0, HASH_INPUT_SIZE - cx->klen); /* xor ipad into key value */ for(i = 0; i < HASH_INPUT_SIZE / sizeof(unsigned long); ++i) ((unsigned long*)cx->key)[i] ^= IPAD; /* and start hash operation */ sha_begin(cx->ctx); sha_hash(cx->key, HASH_INPUT_SIZE, cx->ctx); /* mark as now in data mode */ cx->klen = HMAC_IN_DATA; } /* hash the data (if any) */ if(data_len) sha_hash(data, data_len, cx->ctx); }
char *shahash(const char *str) { char read_buffer[65]; //int read_buffer[64]; int c=1, i; INT64 length=0; int strsz; static char final[40]; int *hashval; hashval = (int *)malloc(20); sha_init(hashval); strsz = strlen(str); if(strsz == 0) { memset(read_buffer, 0, 65); read_buffer[0] = 0x80; sha_hash((int *)read_buffer, hashval); } while (strsz>0) { memset(read_buffer, 0, 65); strncpy((char*)read_buffer, str, 64); c = strlen((char *)read_buffer); length+=c; strsz-=c; if (strsz<=0) { length<<=3; read_buffer[c]=(char)0x80; for (i=c+1; i<64; i++) read_buffer[i]=0; if (c>55) { /* we need to do an entire new block */ sha_hash((int *)read_buffer, hashval); for (i=0; i<14; i++) ((int*)read_buffer)[i]=0; } #ifndef WORDS_BIGENDIAN for (i=0; i<8; i++) { read_buffer[56+i]=(char)(length>>(56-(i*8))) & 0xff; } #else memcpy(read_buffer+56, &length, 8); #endif } sha_hash((int *)read_buffer, hashval); str+=64; }
//Generate a verification key using two null-terminated strings //Concatenates the strings together then hashes them with sha_hash unsigned char *create_v_key(char* data1, char *data2) { char *tmp = string_cat(2,data1,data2); //TODO XOR these instead? unsigned char* key = sha_hash((unsigned char *)tmp, (long)strlen(tmp)); free(tmp); return key; }
/* static int check_default(const char *s, int len) { char tst[64]; register char *x = s; if (len!=7) return 0; //snprintf(tst,len+1,"%s",s); getprint(s,len,tst); dbger("checkd(): %s",tst); if (*x != 'n') return 0; len--; if(len < 0) return 0; x++; if (*x != 'o') return 0; len--; if(len < 0) return 0; x++; if (*x != 'm') return 0; len--; if(len < 0) return 0; x++; if (*x != 'a') return 0; len--; if(len < 0) return 0; x++; if (*x != 't') return 0; len--; if(len < 0) return 0; x++; if (*x != 'c') return 0; len--; if(len < 0) return 0; x++; if (*x != 'h') return 0; len--; if(len < 0) return 0; x++; dbger("match_default_entry"); return 1; } */ static uint32 gethash(const char *s, uint32 slen) { if (slen == 0) return 0U; #ifdef SHASTRID return sha_hash(s,slen); #else return cdb_hash(s,slen); #endif }
/* input the HMAC key (can be called multiple times) */ int hmac_sha_key(const unsigned char key[], unsigned long key_len, hmac_ctx cx[1]) { if(cx->klen == HMAC_IN_DATA) /* error if further key input */ return HMAC_BAD_MODE; /* is attempted in data mode */ if(cx->klen + key_len > HASH_INPUT_SIZE) /* if the key has to be hashed */ { if(cx->klen <= HASH_INPUT_SIZE) /* if the hash has not yet been */ { /* started, initialise it and */ sha_begin(cx->ctx); /* hash stored key characters */ sha_hash(cx->key, cx->klen, cx->ctx); } sha_hash(key, key_len, cx->ctx); /* hash long key data into hash */ } else /* otherwise store key data */ memcpy(cx->key + cx->klen, key, key_len); cx->klen += key_len; /* update the key length count */ return HMAC_OK; }
/* compute and output the MAC value */ void hmac_sha_end(unsigned char mac[], unsigned long mac_len, hmac_ctx cx[1]) { unsigned char dig[HASH_OUTPUT_SIZE]; unsigned int i; /* if no data has been entered perform a null data phase */ if(cx->klen != HMAC_IN_DATA) hmac_sha_data((const unsigned char*)0, 0, cx); sha_end(dig, cx->ctx); /* complete the inner hash */ /* set outer key value using opad and removing ipad */ for(i = 0; i < HASH_INPUT_SIZE / sizeof(unsigned long); ++i) ((unsigned long*)cx->key)[i] ^= OPAD ^ IPAD; /* perform the outer hash operation */ sha_begin(cx->ctx); sha_hash(cx->key, HASH_INPUT_SIZE, cx->ctx); sha_hash(dig, HASH_OUTPUT_SIZE, cx->ctx); sha_end(dig, cx->ctx); /* output the hash value */ for(i = 0; i < mac_len; ++i) mac[i] = dig[i]; }
int main() { int cfd = -1, i; struct cryptodev_ctx ctx; uint8_t digest[20]; char text[] = "The quick brown fox jumps over the lazy dog"; uint8_t expected[] = "\x2f\xd4\xe1\xc6\x7a\x2d\x28\xfc\xed\x84\x9e\xe1\xbb\x76\xe7\x39\x1b\x93\xeb\x12"; /* Open the crypto device */ cfd = open("/dev/crypto", O_RDWR, 0); if (cfd < 0) { perror("open(/dev/crypto)"); return 1; } /* Set close-on-exec (not really neede here) */ if (fcntl(cfd, F_SETFD, 1) == -1) { perror("fcntl(F_SETFD)"); return 1; } sha_ctx_init(&ctx, cfd, NULL, 0); sha_hash(&ctx, text, strlen(text), digest); sha_ctx_deinit(&ctx); printf("digest: "); for (i = 0; i < 20; i++) { printf("%02x:", digest[i]); } printf("\n"); if (memcmp(digest, expected, 20) != 0) { fprintf(stderr, "SHA1 hashing failed\n"); return 1; } /* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; } return 0; }
CK_RV digest_mgr_digest( STDLL_TokData_t *tokdata, SESSION *sess, CK_BBOOL length_only, DIGEST_CONTEXT *ctx, CK_BYTE *in_data, CK_ULONG in_data_len, CK_BYTE *out_data, CK_ULONG *out_data_len ) { CK_RV rc; if (!sess || !ctx){ TRACE_ERROR("Invalid function arguments.\n"); return CKR_FUNCTION_FAILED; } if (ctx->active == FALSE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED)); return CKR_OPERATION_NOT_INITIALIZED; } // if the caller just wants the encrypted length, there is no reason to // specify the input data. I just need the data length // if ((length_only == FALSE) && (!in_data || !out_data)){ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED)); rc = CKR_FUNCTION_FAILED; goto out; } if (ctx->multi == TRUE){ TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_ACTIVE)); rc = CKR_OPERATION_ACTIVE; goto out; } switch (ctx->mech.mechanism) { case CKM_SHA_1: case CKM_SHA256: case CKM_SHA384: case CKM_SHA512: rc = sha_hash( tokdata, sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); break; #if !(NOMD2 ) case CKM_MD2: rc = md2_hash( tokdata, sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); break; #endif case CKM_MD5: rc = md5_hash( tokdata, sess, length_only, ctx, in_data, in_data_len, out_data, out_data_len ); break; default: TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID)); rc = CKR_MECHANISM_INVALID; } out: if ( !((rc == CKR_BUFFER_TOO_SMALL) || (rc == CKR_OK && length_only == TRUE)) ) { // "A call to C_Digest always terminates the active digest operation unless it // returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e., one which returns CKR_OK) // to determine the length of the buffer needed to hold the message digest." digest_mgr_cleanup(ctx); } return rc; }
/* * hash the password */ void do_sha_hash(int *hashval, int *pw) { sha_init(hashval); sha_hash(pw, hashval); }
NOINLINE sha_crypt(/*const*/ char *key_data, /*const*/ char *salt_data) { void (*sha_begin)(void *ctx) FAST_FUNC; void (*sha_hash)(void *ctx, const void *buffer, size_t len) FAST_FUNC; void (*sha_end)(void *ctx, void *resbuf) FAST_FUNC; int _32or64; char *result, *resptr; /* btw, sha256 needs [32] and uint32_t only */ struct { unsigned char alt_result[64]; unsigned char temp_result[64]; union { sha256_ctx_t x; sha512_ctx_t y; } ctx; union { sha256_ctx_t x; sha512_ctx_t y; } alt_ctx; } L __attribute__((__aligned__(__alignof__(uint64_t)))); #define alt_result (L.alt_result ) #define temp_result (L.temp_result) #define ctx (L.ctx ) #define alt_ctx (L.alt_ctx ) unsigned salt_len; unsigned key_len; unsigned cnt; unsigned rounds; char *cp; char is_sha512; /* Analyze salt, construct already known part of result */ cnt = strlen(salt_data) + 1 + 43 + 1; is_sha512 = salt_data[1]; if (is_sha512 == '6') cnt += 43; result = resptr = xzalloc(cnt); /* will provide NUL terminator */ *resptr++ = '$'; *resptr++ = is_sha512; *resptr++ = '$'; rounds = ROUNDS_DEFAULT; salt_data += 3; if (strncmp(salt_data, str_rounds, 7) == 0) { /* 7 == strlen("rounds=") */ char *endp; cnt = bb_strtou(salt_data + 7, &endp, 10); if (*endp == '$') { salt_data = endp + 1; rounds = cnt; if (rounds < ROUNDS_MIN) rounds = ROUNDS_MIN; if (rounds > ROUNDS_MAX) rounds = ROUNDS_MAX; /* add "rounds=NNNNN$" to result */ resptr += sprintf(resptr, str_rounds, rounds); } } salt_len = strchrnul(salt_data, '$') - salt_data; if (salt_len > SALT_LEN_MAX) salt_len = SALT_LEN_MAX; /* xstrdup assures suitable alignment; also we will use it as a scratch space later. */ salt_data = xstrndup(salt_data, salt_len); /* add "salt$" to result */ strcpy(resptr, salt_data); resptr += salt_len; *resptr++ = '$'; /* key data doesn't need much processing */ key_len = strlen(key_data); key_data = xstrdup(key_data); /* Which flavor of SHAnnn ops to use? */ sha_begin = (void*)sha256_begin; sha_hash = (void*)sha256_hash; sha_end = (void*)sha256_end; _32or64 = 32; if (is_sha512 == '6') { sha_begin = (void*)sha512_begin; sha_hash = (void*)sha512_hash; sha_end = (void*)sha512_end; _32or64 = 64; } /* Add KEY, SALT. */ sha_begin(&ctx); sha_hash(&ctx, key_data, key_len); sha_hash(&ctx, salt_data, salt_len); /* Compute alternate SHA sum with input KEY, SALT, and KEY. The final result will be added to the first context. */ sha_begin(&alt_ctx); sha_hash(&alt_ctx, key_data, key_len); sha_hash(&alt_ctx, salt_data, salt_len); sha_hash(&alt_ctx, key_data, key_len); sha_end(&alt_ctx, alt_result); /* Add result of this to the other context. */ /* Add for any character in the key one byte of the alternate sum. */ for (cnt = key_len; cnt > _32or64; cnt -= _32or64) sha_hash(&ctx, alt_result, _32or64); sha_hash(&ctx, alt_result, cnt); /* Take the binary representation of the length of the key and for every 1 add the alternate sum, for every 0 the key. */ for (cnt = key_len; cnt != 0; cnt >>= 1) if ((cnt & 1) != 0) sha_hash(&ctx, alt_result, _32or64); else sha_hash(&ctx, key_data, key_len); /* Create intermediate result. */ sha_end(&ctx, alt_result); /* Start computation of P byte sequence. */ /* For every character in the password add the entire password. */ sha_begin(&alt_ctx); for (cnt = 0; cnt < key_len; ++cnt) sha_hash(&alt_ctx, key_data, key_len); sha_end(&alt_ctx, temp_result); /* NB: past this point, raw key_data is not used anymore */ /* Create byte sequence P. */ #define p_bytes key_data /* reuse the buffer as it is of the key_len size */ cp = p_bytes; /* was: ... = alloca(key_len); */ for (cnt = key_len; cnt >= _32or64; cnt -= _32or64) { cp = memcpy(cp, temp_result, _32or64); cp += _32or64; } memcpy(cp, temp_result, cnt); /* Start computation of S byte sequence. */ /* For every character in the password add the entire password. */ sha_begin(&alt_ctx); for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) sha_hash(&alt_ctx, salt_data, salt_len); sha_end(&alt_ctx, temp_result); /* NB: past this point, raw salt_data is not used anymore */ /* Create byte sequence S. */ #define s_bytes salt_data /* reuse the buffer as it is of the salt_len size */ cp = s_bytes; /* was: ... = alloca(salt_len); */ for (cnt = salt_len; cnt >= _32or64; cnt -= _32or64) { cp = memcpy(cp, temp_result, _32or64); cp += _32or64; } memcpy(cp, temp_result, cnt); /* Repeatedly run the collected hash value through SHA to burn CPU cycles. */ for (cnt = 0; cnt < rounds; ++cnt) { sha_begin(&ctx); /* Add key or last result. */ if ((cnt & 1) != 0) sha_hash(&ctx, p_bytes, key_len); else sha_hash(&ctx, alt_result, _32or64); /* Add salt for numbers not divisible by 3. */ if (cnt % 3 != 0) sha_hash(&ctx, s_bytes, salt_len); /* Add key for numbers not divisible by 7. */ if (cnt % 7 != 0) sha_hash(&ctx, p_bytes, key_len); /* Add key or last result. */ if ((cnt & 1) != 0) sha_hash(&ctx, alt_result, _32or64); else sha_hash(&ctx, p_bytes, key_len); sha_end(&ctx, alt_result); } /* Append encrypted password to result buffer */ //TODO: replace with something like // bb_uuencode(cp, src, length, bb_uuenc_tbl_XXXbase64); #define b64_from_24bit(B2, B1, B0, N) \ do { \ unsigned w = ((B2) << 16) | ((B1) << 8) | (B0); \ resptr = to64(resptr, w, N); \ } while (0) if (is_sha512 == '5') { unsigned i = 0; while (1) { unsigned j = i + 10; unsigned k = i + 20; if (j >= 30) j -= 30; if (k >= 30) k -= 30; b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4); if (k == 29) break; i = k + 1; } b64_from_24bit(0, alt_result[31], alt_result[30], 3); /* was: b64_from_24bit(alt_result[0], alt_result[10], alt_result[20], 4); b64_from_24bit(alt_result[21], alt_result[1], alt_result[11], 4); b64_from_24bit(alt_result[12], alt_result[22], alt_result[2], 4); b64_from_24bit(alt_result[3], alt_result[13], alt_result[23], 4); b64_from_24bit(alt_result[24], alt_result[4], alt_result[14], 4); b64_from_24bit(alt_result[15], alt_result[25], alt_result[5], 4); b64_from_24bit(alt_result[6], alt_result[16], alt_result[26], 4); b64_from_24bit(alt_result[27], alt_result[7], alt_result[17], 4); b64_from_24bit(alt_result[18], alt_result[28], alt_result[8], 4); b64_from_24bit(alt_result[9], alt_result[19], alt_result[29], 4); b64_from_24bit(0, alt_result[31], alt_result[30], 3); */ } else { unsigned i = 0; while (1) { unsigned j = i + 21; unsigned k = i + 42; if (j >= 63) j -= 63; if (k >= 63) k -= 63; b64_from_24bit(alt_result[i], alt_result[j], alt_result[k], 4); if (j == 20) break; i = j + 1; } b64_from_24bit(0, 0, alt_result[63], 2); /* was: b64_from_24bit(alt_result[0], alt_result[21], alt_result[42], 4); b64_from_24bit(alt_result[22], alt_result[43], alt_result[1], 4); b64_from_24bit(alt_result[44], alt_result[2], alt_result[23], 4); b64_from_24bit(alt_result[3], alt_result[24], alt_result[45], 4); b64_from_24bit(alt_result[25], alt_result[46], alt_result[4], 4); b64_from_24bit(alt_result[47], alt_result[5], alt_result[26], 4); b64_from_24bit(alt_result[6], alt_result[27], alt_result[48], 4); b64_from_24bit(alt_result[28], alt_result[49], alt_result[7], 4); b64_from_24bit(alt_result[50], alt_result[8], alt_result[29], 4); b64_from_24bit(alt_result[9], alt_result[30], alt_result[51], 4); b64_from_24bit(alt_result[31], alt_result[52], alt_result[10], 4); b64_from_24bit(alt_result[53], alt_result[11], alt_result[32], 4); b64_from_24bit(alt_result[12], alt_result[33], alt_result[54], 4); b64_from_24bit(alt_result[34], alt_result[55], alt_result[13], 4); b64_from_24bit(alt_result[56], alt_result[14], alt_result[35], 4); b64_from_24bit(alt_result[15], alt_result[36], alt_result[57], 4); b64_from_24bit(alt_result[37], alt_result[58], alt_result[16], 4); b64_from_24bit(alt_result[59], alt_result[17], alt_result[38], 4); b64_from_24bit(alt_result[18], alt_result[39], alt_result[60], 4); b64_from_24bit(alt_result[40], alt_result[61], alt_result[19], 4); b64_from_24bit(alt_result[62], alt_result[20], alt_result[41], 4); b64_from_24bit(0, 0, alt_result[63], 2); */ } /* *resptr = '\0'; - xzalloc did it */ #undef b64_from_24bit /* Clear the buffer for the intermediate result so that people attaching to processes or reading core dumps cannot get any information. */ memset(&L, 0, sizeof(L)); /* [alt]_ctx and XXX_result buffers */ memset(key_data, 0, key_len); /* also p_bytes */ memset(salt_data, 0, salt_len); /* also s_bytes */ free(key_data); free(salt_data); #undef p_bytes #undef s_bytes return result; #undef alt_result #undef temp_result #undef ctx #undef alt_ctx }