Description
Properties
| Name | Value |
|---|---|
| ANSI Nulls ON | True |
| Quoted Identifier ON | True |
| Encrypted | False |
| Execute As | |
| Assembly |
Parameters
5| Name | Data Type | Length | Description |
|---|---|---|---|
| @PasswordStr | varchar | -1 | |
| @SaltStr | varchar | -1 | |
| @IterationCount | int | 4 | |
| @Outputbytes | int | 4 | |
| @VDO3_PWD | varchar | -1 |
SQL Script
Copy
SET QUOTED_IDENTIFIER, ANSI_NULLS ON
GO
CREATE OR ALTER PROCEDURE dbo.VDO3_CRYPT_SP
(
@PasswordStr VARCHAR(MAX), -- HASHBYTES is limited, and HMAC concatenation limits this more, though 4000 is a guess
@SaltStr VARCHAR(MAX), -- HASHBYTES is limited, and HMAC concatenation limits this more, though 4000 is a guess
@IterationCount INT,
@Outputbytes INT, -- For password hashing, should "naturally" be the digest size (or less) - more than the digest size allows the first <digest size> to remain identical, so someone cracking the PBKDF2'd passwords only needs to generate and check the first <digest size>
@VDO3_PWD VARCHAR(MAX) OUTPUT
)
AS
BEGIN
declare @Password varbinary(max)
select @Password = cast(@PasswordStr as varbinary(max))
declare @Salt varbinary(max)
select @Salt = cast(@SaltStr as varbinary(max))
-- WARNING - if you are using SQL 2012 or better, DO NOT USE Yourfn_CRYPT_PBKDF2_VARBINARY_SHA1 UNLESS YOU NEED BACKWARDS COMPATIBILITY!!! The 64-bit math required by SHA-512 (and SHA-384) is proportionally faster on CPUs vs. GPU's as of 2013, which reduces a GPU based attacker's advantage.
-- SEE PKCS #5, RFC2898, as well as PBKDF2, i.e. http://tools.ietf.org/rfc/rfc2898.txt
-- WARNING - SQL is NOT a good language for this type of math; results are fairly slow, and are generally better off being implemented by another language.
-- This is a dedicated HMAC-SHA-512 version, with a moderate amount of performance tuning.
DECLARE @NumDigestSizesRequiredToEncompassOutputbytes INT
DECLARE @RemainderOutputbytesAfterNumDigestSizesMinusOne INT
DECLARE @Working BINARY(64) -- digest size
DECLARE @ThisIterationResult BINARY(64) -- digest size
DECLARE @FirstIterationDefinedResult VARBINARY(4004) -- Salt size + INT size per HMAC definition
DECLARE @output VARBINARY(8000)
DECLARE @CurrentDigestSizeChunk INT
DECLARE @CurrentIteration INT
-- Start Inlined HMAC-SHA-512 variables
DECLARE @ipadRFC2104 BIGINT
DECLARE @opadRFC2104 BIGINT
DECLARE @k_ipadRFC2104 BINARY(128) -- BLOCKSIZE in bytes per HMAC definition
DECLARE @k_opadRFC2104 BINARY(128) -- BLOCKSIZE in bytes per HMAC definition
--SQL fails to allow binary operations on two binary data types!!! We use bigint and iterate 8 times for 512 bits = 64 byte blocksize for better performance.
SET @ipadRFC2104 = CAST(0x3636363636363636 AS BIGINT)
SET @opadRFC2104 = CAST(0x5C5C5C5C5C5C5C5C AS BIGINT)
-- End Inlined HMAC-SHA-512 variables
SET @NumDigestSizesRequiredToEncompassOutputbytes = (@Outputbytes + 63)/64 -- number > 1 is digest size/digest size minus 1
SET @RemainderOutputbytesAfterNumDigestSizesMinusOne = @Outputbytes - (@NumDigestSizesRequiredToEncompassOutputbytes - 1) * 64 -- the number in here that's > 1 is the digest size
SET @output = 0x
SET @CurrentDigestSizeChunk = 1
WHILE @CurrentDigestSizeChunk <= @NumDigestSizesRequiredToEncompassOutputbytes
BEGIN
SET @FirstIterationDefinedResult = @Salt + CAST(@CurrentDigestSizeChunk AS VARBINARY(4))
--SET @ThisIterationResult = YourDB.dbo.Yourfn_CRYPT_HMAC_SHA512(@Password,@FirstIterationDefinedResult)
-- NOTE: Inlining HMAC-SHA-512 appears to improve performance by a factor of six or so. Setting the HMAC as an Inlined Table Valued Function instead of a Scalar function would reduce this disparity, of course.
-- START INLINED HMAC-SHA-512 for performance improvement
-- B = BLOCKSIZE (64 bytes for MD5, SHA-224, SHA-256, and 128 bytes for SHA-384 and SHA-512, per RFC2104 and RFC4868)
IF LEN(@Password) > 128 -- Applications that use keys longer than B bytes will first hash the key using H and then use the resultant L byte string as the actual key to HMAC
SET @Password = CAST(HASHBYTES('SHA2_512', @Password) AS BINARY (128))
ELSE
SET @Password = CAST(@Password AS BINARY (128)) -- append zeros to the end of K to create a B byte string
-- Loop unrolled for definite performance benefit
-- Must XOR BLOCKSIZE bytes
SET @k_ipadRFC2104 = CONVERT(BINARY(8),(SUBSTRING(@Password, 1, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 9, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 17, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 25, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 33, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 41, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 49, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 57, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 65, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 73, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 81, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 89, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 97, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 105, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 113, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 121, 8) ^ @ipadRFC2104))
-- Loop unrolled for definite performance benefit
-- Must XOR BLOCKSIZE bytes
SET @k_opadRFC2104 = CONVERT(BINARY(8),(SUBSTRING(@Password, 1, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 9, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 17, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 25, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 33, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 41, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 49, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 57, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 65, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 73, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 81, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 89, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 97, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 105, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 113, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 121, 8) ^ @opadRFC2104))
SET @ThisIterationResult = HASHBYTES('SHA2_512', @k_opadRFC2104 + HASHBYTES('SHA2_512', @k_ipadRFC2104 + @FirstIterationDefinedResult))
-- END INLINED HMAC-SHA-512 for performance improvement
SET @Working = @ThisIterationResult
SET @CurrentIteration = 1
WHILE @CurrentIteration < @IterationCount
BEGIN
--SET @ThisIterationResult = YourDB.dbo.Yourfn_CRYPT_HMAC_SHA512(@Password,@ThisIterationResult)
-- NOTE: Inlining HMAC-SHA-512 appears to improve performance by a factor of six or so. Setting the HMAC as an Inlined Table Valued Function instead of a Scalar function would reduce this disparity, of course.
-- START INLINED HMAC-SHA-512 for performance improvement
-- B = BLOCKSIZE (64 bytes for MD5, SHA-224, SHA-256, and 128 bytes for SHA-384 and SHA-512, per RFC2104 and RFC4868)
-- We've already hashed the password if we needed to!
-- We've already generated @k_ipadRFC2104 and @k_opadRFC2104 both!
SET @ThisIterationResult = HASHBYTES('SHA2_512', @k_opadRFC2104 + HASHBYTES('SHA2_512', @k_ipadRFC2104 + @ThisIterationResult))
-- END INLINED HMAC-SHA-512 for performance improvement
-- Loop unrolled for possible performance benefit
-- Stupid conversion required because SQL Server can't do binary operations on two binary variables!!!
-- Must XOR digest size bytes
SET @Working = CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,1,8)))^SUBSTRING(@Working,1,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,9,8)))^SUBSTRING(@Working,9,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,17,8)))^SUBSTRING(@Working,17,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,25,8)))^SUBSTRING(@Working,25,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,33,8)))^SUBSTRING(@Working,33,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,41,8)))^SUBSTRING(@Working,41,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,49,8)))^SUBSTRING(@Working,49,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,57,8)))^SUBSTRING(@Working,57,8)))
SET @CurrentIteration += 1 -- SHA-512 is a SQL 2012 only function, so SQL 2008 only syntax doesn't limit compatibility any further.
END -- WHILE @CurrentIteration rounds
SELECT @output = @output +
CASE
WHEN @CurrentDigestSizeChunk = @NumDigestSizesRequiredToEncompassOutputbytes THEN CONVERT(BINARY(64),LEFT(@Working,@RemainderOutputbytesAfterNumDigestSizesMinusOne)) -- digest size in bytes
ELSE CONVERT(BINARY(64),@Working) -- digest size in bytes
END
SET @CurrentDigestSizeChunk += 1 -- SHA-512 is a SQL 2012 only function, so SQL 2008 only syntax doesn't limit compatibility any further.
END
/*
RETURN @output
*/
SET @VDO3_PWD = CONVERT(varchar(max),@OUTPUT)
END
GO
GO
CREATE OR ALTER PROCEDURE dbo.VDO3_CRYPT_SP
(
@PasswordStr VARCHAR(MAX), -- HASHBYTES is limited, and HMAC concatenation limits this more, though 4000 is a guess
@SaltStr VARCHAR(MAX), -- HASHBYTES is limited, and HMAC concatenation limits this more, though 4000 is a guess
@IterationCount INT,
@Outputbytes INT, -- For password hashing, should "naturally" be the digest size (or less) - more than the digest size allows the first <digest size> to remain identical, so someone cracking the PBKDF2'd passwords only needs to generate and check the first <digest size>
@VDO3_PWD VARCHAR(MAX) OUTPUT
)
AS
BEGIN
declare @Password varbinary(max)
select @Password = cast(@PasswordStr as varbinary(max))
declare @Salt varbinary(max)
select @Salt = cast(@SaltStr as varbinary(max))
-- WARNING - if you are using SQL 2012 or better, DO NOT USE Yourfn_CRYPT_PBKDF2_VARBINARY_SHA1 UNLESS YOU NEED BACKWARDS COMPATIBILITY!!! The 64-bit math required by SHA-512 (and SHA-384) is proportionally faster on CPUs vs. GPU's as of 2013, which reduces a GPU based attacker's advantage.
-- SEE PKCS #5, RFC2898, as well as PBKDF2, i.e. http://tools.ietf.org/rfc/rfc2898.txt
-- WARNING - SQL is NOT a good language for this type of math; results are fairly slow, and are generally better off being implemented by another language.
-- This is a dedicated HMAC-SHA-512 version, with a moderate amount of performance tuning.
DECLARE @NumDigestSizesRequiredToEncompassOutputbytes INT
DECLARE @RemainderOutputbytesAfterNumDigestSizesMinusOne INT
DECLARE @Working BINARY(64) -- digest size
DECLARE @ThisIterationResult BINARY(64) -- digest size
DECLARE @FirstIterationDefinedResult VARBINARY(4004) -- Salt size + INT size per HMAC definition
DECLARE @output VARBINARY(8000)
DECLARE @CurrentDigestSizeChunk INT
DECLARE @CurrentIteration INT
-- Start Inlined HMAC-SHA-512 variables
DECLARE @ipadRFC2104 BIGINT
DECLARE @opadRFC2104 BIGINT
DECLARE @k_ipadRFC2104 BINARY(128) -- BLOCKSIZE in bytes per HMAC definition
DECLARE @k_opadRFC2104 BINARY(128) -- BLOCKSIZE in bytes per HMAC definition
--SQL fails to allow binary operations on two binary data types!!! We use bigint and iterate 8 times for 512 bits = 64 byte blocksize for better performance.
SET @ipadRFC2104 = CAST(0x3636363636363636 AS BIGINT)
SET @opadRFC2104 = CAST(0x5C5C5C5C5C5C5C5C AS BIGINT)
-- End Inlined HMAC-SHA-512 variables
SET @NumDigestSizesRequiredToEncompassOutputbytes = (@Outputbytes + 63)/64 -- number > 1 is digest size/digest size minus 1
SET @RemainderOutputbytesAfterNumDigestSizesMinusOne = @Outputbytes - (@NumDigestSizesRequiredToEncompassOutputbytes - 1) * 64 -- the number in here that's > 1 is the digest size
SET @output = 0x
SET @CurrentDigestSizeChunk = 1
WHILE @CurrentDigestSizeChunk <= @NumDigestSizesRequiredToEncompassOutputbytes
BEGIN
SET @FirstIterationDefinedResult = @Salt + CAST(@CurrentDigestSizeChunk AS VARBINARY(4))
--SET @ThisIterationResult = YourDB.dbo.Yourfn_CRYPT_HMAC_SHA512(@Password,@FirstIterationDefinedResult)
-- NOTE: Inlining HMAC-SHA-512 appears to improve performance by a factor of six or so. Setting the HMAC as an Inlined Table Valued Function instead of a Scalar function would reduce this disparity, of course.
-- START INLINED HMAC-SHA-512 for performance improvement
-- B = BLOCKSIZE (64 bytes for MD5, SHA-224, SHA-256, and 128 bytes for SHA-384 and SHA-512, per RFC2104 and RFC4868)
IF LEN(@Password) > 128 -- Applications that use keys longer than B bytes will first hash the key using H and then use the resultant L byte string as the actual key to HMAC
SET @Password = CAST(HASHBYTES('SHA2_512', @Password) AS BINARY (128))
ELSE
SET @Password = CAST(@Password AS BINARY (128)) -- append zeros to the end of K to create a B byte string
-- Loop unrolled for definite performance benefit
-- Must XOR BLOCKSIZE bytes
SET @k_ipadRFC2104 = CONVERT(BINARY(8),(SUBSTRING(@Password, 1, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 9, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 17, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 25, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 33, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 41, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 49, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 57, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 65, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 73, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 81, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 89, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 97, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 105, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 113, 8) ^ @ipadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 121, 8) ^ @ipadRFC2104))
-- Loop unrolled for definite performance benefit
-- Must XOR BLOCKSIZE bytes
SET @k_opadRFC2104 = CONVERT(BINARY(8),(SUBSTRING(@Password, 1, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 9, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 17, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 25, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 33, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 41, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 49, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 57, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 65, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 73, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 81, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 89, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 97, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 105, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 113, 8) ^ @opadRFC2104))
+ CONVERT(BINARY(8),(SUBSTRING(@Password, 121, 8) ^ @opadRFC2104))
SET @ThisIterationResult = HASHBYTES('SHA2_512', @k_opadRFC2104 + HASHBYTES('SHA2_512', @k_ipadRFC2104 + @FirstIterationDefinedResult))
-- END INLINED HMAC-SHA-512 for performance improvement
SET @Working = @ThisIterationResult
SET @CurrentIteration = 1
WHILE @CurrentIteration < @IterationCount
BEGIN
--SET @ThisIterationResult = YourDB.dbo.Yourfn_CRYPT_HMAC_SHA512(@Password,@ThisIterationResult)
-- NOTE: Inlining HMAC-SHA-512 appears to improve performance by a factor of six or so. Setting the HMAC as an Inlined Table Valued Function instead of a Scalar function would reduce this disparity, of course.
-- START INLINED HMAC-SHA-512 for performance improvement
-- B = BLOCKSIZE (64 bytes for MD5, SHA-224, SHA-256, and 128 bytes for SHA-384 and SHA-512, per RFC2104 and RFC4868)
-- We've already hashed the password if we needed to!
-- We've already generated @k_ipadRFC2104 and @k_opadRFC2104 both!
SET @ThisIterationResult = HASHBYTES('SHA2_512', @k_opadRFC2104 + HASHBYTES('SHA2_512', @k_ipadRFC2104 + @ThisIterationResult))
-- END INLINED HMAC-SHA-512 for performance improvement
-- Loop unrolled for possible performance benefit
-- Stupid conversion required because SQL Server can't do binary operations on two binary variables!!!
-- Must XOR digest size bytes
SET @Working = CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,1,8)))^SUBSTRING(@Working,1,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,9,8)))^SUBSTRING(@Working,9,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,17,8)))^SUBSTRING(@Working,17,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,25,8)))^SUBSTRING(@Working,25,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,33,8)))^SUBSTRING(@Working,33,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,41,8)))^SUBSTRING(@Working,41,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,49,8)))^SUBSTRING(@Working,49,8)))
+ CONVERT(BINARY(8),(CONVERT(BIGINT,(SUBSTRING(@ThisIterationResult,57,8)))^SUBSTRING(@Working,57,8)))
SET @CurrentIteration += 1 -- SHA-512 is a SQL 2012 only function, so SQL 2008 only syntax doesn't limit compatibility any further.
END -- WHILE @CurrentIteration rounds
SELECT @output = @output +
CASE
WHEN @CurrentDigestSizeChunk = @NumDigestSizesRequiredToEncompassOutputbytes THEN CONVERT(BINARY(64),LEFT(@Working,@RemainderOutputbytesAfterNumDigestSizesMinusOne)) -- digest size in bytes
ELSE CONVERT(BINARY(64),@Working) -- digest size in bytes
END
SET @CurrentDigestSizeChunk += 1 -- SHA-512 is a SQL 2012 only function, so SQL 2008 only syntax doesn't limit compatibility any further.
END
/*
RETURN @output
*/
SET @VDO3_PWD = CONVERT(varchar(max),@OUTPUT)
END
GO
Depends On
No items found