Question

I have been studying Oracle's mechanism for authenticating against a 10g database. Although it is less documented than its 9i counterpart, I have still managed to find many of its details on various web sites and blogs. One piece remains a mystery, however. Before I mention what is missing, let me explain what is known about the protocol in pseudo code:

// CLIENT SIDE PSEUDO CODE

user = "SCOTT"
password = "TIGER"
password_hash = oracle_password_hash(user, password)

// 1. Client provides user name to server
send(user)

// 2. Server responds with its encrypted AUTH_SESSKEY, 
//    a randomly generated number associated with the current session
encrypted_server_AUTH_SESSKEY = receive_AUTH_SESSKEY() // 32 bytes

decrypted_server_AUTH_SESSKEY = aes_decrypt(
    encrypted_input => encrypted_server_AUTH_SESSKEY,
    decryption_key  => password_hash
)

// 3. Client generates its own AUTH_SESSKEY for this session
unencrypted_client_AUTH_SESSKEY = generate_random_AUTH_SESSKEY() // 32 bytes

encrypted_client_AUTH_SESSKEY = aes_encrypt(
    unencrypted_input => unencrypted_client_AUTH_SESSKEY,
    encryption_key    => password_hash
)

// 4. Client combines the two AUTH_SESSKEYs using a known Oracle-specific algorithm
combined_AUTH_SESSKEYs = oracle_combine(decrypted_server_AUTH_SESSKEY, unencrypted_client_AUTH_SESSKEY)

// 5. Client builds AUTH_PASSWORD
unencrypted_AUTH_PASSWORD = byte[32]
unencrypted_AUTH_PASSWORD[0 .. 16] = ??? // THIS IS THE PROBLEM
unencrypted_AUTH_PASSWORD[16 .. 16 + len(password)] = password
unencrypted_AUTH_PASSWORD[16 + len(password) .. ] = PKCS#7 padding

// 6. Client encrypts the AUTH_PASSWORD data using the combined AUTH_SESSKEYs as the encryption key
encrypted_AUTH_PASSWORD = aes_encrypt(
    unencrypted_input => unencrypted_AUTH_PASSWORD,
    encryption_key    => combined_AUTH_SESSKEYs
)

// 7. Client transmits its encrypted AUTH_SESSKEY and AUTH_PASSWORD to server for verification
send(encrypted_client_AUTH_SESSKEY, encrypted_AUTH_PASSWORD)

What does the Oracle client put in the lower 16 bytes of the AUTH_PASSWORD value in step 5?

Almost all documentation I have found cares only about obtaining the plain text password contained within, paying little attention to these first bytes. I have tried looking at the JDBC driver, but it appears that even the 10g version avoids this authentication scheme by requesting that the server revert back to an older scheme (which happens to be much better understood). An excellent C program demonstrates the decryption of AUTH_PASSWORD.

Can anyone point me in the right direction?

Was it helpful?

Solution

I have determined that the 16 bytes immediately before the plain text password are randomly generated (for the curious, take a look at the ztvo5pe function exported by the oran10.dll library - you will see two successive calls to ztcen, the first call fills it in).

I originally posted the question because I was writing a small program to connect to an Oracle database without the use of Oracle's JDBC driver. I was finding that the database was rejecting my 32-byte AUTH_PASSWORD. I assumed that it was rejected because I had put an incorrect value in these first 16 bytes. I was wrong. It appears that these do not have any effect on whether or not a user authenticates.

Rather, it turns out that the database was rejecting my AUTH_PASSWORD because of the trailing bytes that come immediately after the plain text password. I naively padded the buffer with zeroes. It should have been padded according to the PKCS #7 specification.

OTHER TIPS

If the password length < 16, the first 16 bytes are random data, then the password, the padding data are char of (16 – strlen(password)). The Oracle server can accept my AUTH_PASSWORD. If the password length >= 16, I don’t know how to do it. I filled the first 16 bytes with random data, but the server reject my data. I want to know: are you sure the padding data is according to the PKCS#7 specification.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top