/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.HLE.modules;
import org.apache.log4j.Logger;
import jpcsp.HLE.BufferInfo;
import jpcsp.HLE.BufferInfo.LengthInfo;
import jpcsp.HLE.BufferInfo.Usage;
import jpcsp.HLE.CanBeNull;
import jpcsp.HLE.HLEFunction;
import jpcsp.HLE.HLEModule;
import jpcsp.HLE.Modules;
import jpcsp.HLE.TPointer;
import jpcsp.HLE.TPointer8;
import jpcsp.crypto.CryptoEngine;
import jpcsp.crypto.SAVEDATA;
import jpcsp.util.Utilities;
public class sceChnnlsv extends HLEModule{
public static Logger log = Modules.getLogger("sceChnnlsv");
private CryptoEngine crypto = new CryptoEngine();
/**
* Initialize the SceSdCtx2 struct and set the mode.
*
* @param ctx Pointer to the SceSdCtx2 struct
* @param mode One of the modes whichs sets the scramble key for kirk.
*
* @return SCE_ERROR_OK on initialization success.
* @return SCE_CHNNLSV_ERROR_ILLEGAL_ADDR if ctx cannot be accessed from the current context.
*
*/
@HLEFunction(nid = 0xE7833020, version = 150)
public int sceSdSetIndex(@BufferInfo(lengthInfo=LengthInfo.fixedLength, length=40, usage=Usage.out) TPointer ctx2Addr, int mode) {
SAVEDATA.SD_Ctx1 ctx = new SAVEDATA.SD_Ctx1();
int result = crypto.getSAVEDATAEngine().hleSdSetIndex(ctx, mode);
ctx.write(ctx2Addr);
return result;
}
/**
* Generates a hash storing the result into ctx->data and updates ctx->key
*
* @param ctx Pointer to the SceSdCtx2 struct
* @param data Pointer to the data used in hash generation
* @param size The size of the data used for hash generation
*
* @return SCE_ERROR_OK on success
* @return SCE_CHNNLSV_ERROR_ILLEGAL_ADDR if ctx/data cannot be accessed from the current context.
* @return SCE_CHNNLSV_ERROR_SEMA_ERROR wait/signal sema error
* @return SCE_CHNNLSV_ERROR_ILLEGAL_SIZE if ctx->size > 16
*
*/
@HLEFunction(nid = 0xF21A1FCA, version = 150)
public int sceSdRemoveValue(@BufferInfo(lengthInfo=LengthInfo.fixedLength, length=40, usage=Usage.inout) TPointer ctx2Addr, @BufferInfo(lengthInfo=LengthInfo.nextParameter, usage=Usage.in) TPointer data, int size) {
SAVEDATA.SD_Ctx1 ctx = new SAVEDATA.SD_Ctx1();
ctx.read(ctx2Addr);
byte[] bytes = new byte[size];
Utilities.readBytes(data.getAddress(), size, bytes, 0);
int result = crypto.getSAVEDATAEngine().hleSdRemoveValue(ctx, bytes, size);
ctx.write(ctx2Addr);
return result;
}
/**
* Generates a hash based on the context collected by sceSdRemoveValue,
* the results of which are stored into the SAVEDATA_PARAMS field of PARAM.SFO
*
* @param ctx Pointer to the SceSdCtx2 struct
* @param hash The end result of the hash generated by this function is stored here
* @param key If provided, this key will also be used in the encryption process
*
* @return SCE_ERROR_OK on success
* @return SCE_CHNNLSV_ERROR_ILLEGAL_ADDR if ctx/hash/key cannot be accessed from the current context.
* @return SCE_CHNNLSV_ERROR_SEMA_ERROR wait/signal sema error
* @return SCE_CHNNLSV_ERROR_ILLEGAL_SIZE if ctx->size > 16
*
*/
@HLEFunction(nid = 0xC4C494F8, version = 150)
public int sceSdGetLastIndex(@BufferInfo(lengthInfo=LengthInfo.fixedLength, length=40, usage=Usage.inout) TPointer ctx2Addr, @BufferInfo(lengthInfo=LengthInfo.fixedLength, length=16, usage=Usage.out) TPointer8 hash, @CanBeNull @BufferInfo(lengthInfo=LengthInfo.fixedLength, length=16, usage=Usage.in) TPointer8 key) {
SAVEDATA.SD_Ctx1 ctx = new SAVEDATA.SD_Ctx1();
ctx.read(ctx2Addr);
byte[] hashBytes = new byte[16];
byte[] keyBytes;
if (key.isNull()) {
keyBytes = null;
} else {
keyBytes = new byte[16];
Utilities.readBytes(key.getAddress(), keyBytes.length, keyBytes, 0);
}
int result = crypto.getSAVEDATAEngine().hleSdGetLastIndex(ctx, hashBytes, keyBytes);
Utilities.writeBytes(hash.getAddress(), hashBytes.length, hashBytes, 0);
ctx.write(ctx2Addr);
return result;
}
/**
* The main key generating function, 1 for encryption, 2 for decryption
*
* @param ctx Pointer to the SceSdCtx1 struct
* @param mode Different public keys/kirk commands will be used depending on the mode specified
* @param genMode Specify whether encryption (1) or decryption (1) should be used
* @param data Pointer to some data used for encryption/decryption
* @param key If specified, this key will be used as the private key for encryption/decryption
*
* @return SCE_ERROR_OK on success
* @return SCE_CHNNLSV_ERROR_ILLEGAL_ADDR if ctx/data/key cannot be accessed from the current context.
* @return SCE_CHNNLSV_ERROR_SEMA_ERROR wait/signal sema error
*
*/
@HLEFunction(nid = 0xABFDFC8B, version = 150)
public int sceSdCreateList(@BufferInfo(lengthInfo=LengthInfo.fixedLength, length=24, usage=Usage.inout) TPointer ctx2Addr, int encMode, int genMode, @BufferInfo(lengthInfo=LengthInfo.fixedLength, length=16, usage=Usage.inout) TPointer8 data, @CanBeNull @BufferInfo(lengthInfo=LengthInfo.fixedLength, length=16, usage=Usage.in) TPointer8 key) {
SAVEDATA.SD_Ctx2 ctx = new SAVEDATA.SD_Ctx2();
ctx.read(ctx2Addr);
byte[] dataBytes;
if (data.isNull()) {
dataBytes = null;
} else {
dataBytes = new byte[16];
Utilities.readBytes(data.getAddress(), dataBytes.length, dataBytes, 0);
}
byte[] keyBytes;
if (key.isNull()) {
keyBytes = null;
} else {
keyBytes = new byte[16];
Utilities.readBytes(key.getAddress(), keyBytes.length, keyBytes, 0);
}
int result = crypto.getSAVEDATAEngine().hleSdCreateList(ctx, encMode, genMode, dataBytes, keyBytes);
if (dataBytes != null) {
Utilities.writeBytes(data.getAddress(), dataBytes.length, dataBytes, 0);
}
if (keyBytes != null) {
Utilities.writeBytes(key.getAddress(), keyBytes.length, keyBytes, 0);
}
ctx.write(ctx2Addr);
return result;
}
/**
* The main encryption/decryption function, the size of "data" must be 16 byte aligned
*
* @param ctx Pointer to the SceSdCtx1 struct
* @param data Pointer to the data used in the encryption/decryption process
* @param size The size of "data"
*
* @return SCE_ERROR_OK on success
* @return SCE_CHNNLSV_ERROR_ILLEGAL_ADDR if ctx/data cannot be accessed from the current context.
* @return SCE_CHNNLSV_ERROR_SEMA_ERROR wait/signal sema error
* @return SCE_CHNNLSV_ERROR_ILLEGAL_ALIGNMENT_SIZE if the size of "data" is not 16 byte aligned
*
*/
@HLEFunction(nid = 0x850A7FA1, version = 150)
public int sceSdSetMember(@BufferInfo(lengthInfo=LengthInfo.fixedLength, length=24, usage=Usage.inout) TPointer ctx2Addr, @BufferInfo(lengthInfo=LengthInfo.nextParameter, usage=Usage.inout) TPointer8 data, int dataLength) {
SAVEDATA.SD_Ctx2 ctx = new SAVEDATA.SD_Ctx2();
ctx.read(ctx2Addr);
byte[] dataBytes = new byte[dataLength];
Utilities.readBytes(data.getAddress(), dataLength, dataBytes, 0);
int result = crypto.getSAVEDATAEngine().hleSdSetMember(ctx, dataBytes, dataLength);
Utilities.writeBytes(data.getAddress(), dataBytes.length, dataBytes, 0);
ctx.write(ctx2Addr);
return result;
}
/**
* Initialize the SceSdCtx1 struct.
*
* @param ctx Pointer to the SceSdCtx1 struct
*
* @return SCE_ERROR_OK on initialization success.
* @return SCE_CHNNLSV_ERROR_ILLEGAL_ADDR if ctx cannot be accessed from the current context.
*
*/
@HLEFunction(nid = 0x21BE78B4, version = 150)
public int sceSdCleanList(@BufferInfo(lengthInfo=LengthInfo.fixedLength, length=24, usage=Usage.out) TPointer ctx2Addr) {
SAVEDATA.SD_Ctx2 ctx = new SAVEDATA.SD_Ctx2();
ctx.read(ctx2Addr);
int result = crypto.getSAVEDATAEngine().hleSdCleanList(ctx);
ctx.write(ctx2Addr);
return result;
}
}