ALG_RSA_NOPAD Illegal Use Exception despite message in proper alignment in Java Card - cryptography

I am trying to use an RSA private key to "encrypt" a message (I am trying to use the RSA encrypt operation for the use of the raw modulus exponential operation similar to the Diffie-Hellman) using the ALG_RSA_NOPAD algorithm in a JavaCard environment. I am getting the ILLEGAL_USE Exception despite ensuring my hard-coded message is zero filled by hard-coding as shown in the code below.
private byte[] M = {
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, //25
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 50
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 75
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 100
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 125
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 150
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 175
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 200
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 225
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 250
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x02 // 256
};
priv = (RSAPrivateKey) KeyBuilder.buildKey(KeyBuilder.TYPE_RSA_PRIVATE_TRANSIENT_RESET, KeyBuilder.LENGTH_RSA_2048, false);
cipher = Cipher.getInstance(Cipher.ALG_RSA_NOPAD, false);
KeyPair keyPair = new KeyPair(KeyPair.ALG_RSA, (short) priv.getSize());
keyPair.genKeyPair();
priv = (RSAPrivateKey) keyPair.getPrivate();
cipher.init(priv, Cipher.MODE_ENCRYPT);
cipher.doFinal(M, (short) 0, (short) 256, buff, (short) 0); // Encrypt hard-coded message M
What am I missing ?

PrivateKey classes are not able to use ENCRYPT mode which the use of DECRYPT mode is the only option to get the RSA modulus exponential mechanism to work with a PrivateKey.

Related

MFT File entry having multiple Filename attributes and a Reparse point

I am reading MFT Entries of NTFS file system.
I know that MFT can have multiple FileName attributes, which are created when we create hard links. I know that Junctions/Symbolic links can be created for directories. Junction / Symbolic link are implemented using Reparse points.
While reading a VHD file formatted with NTFS filesystem, I find that there are some MFT entries for "Directories" having multiple Filename attributes and single Reparse point.
Is it possible for directories to have hardlinks (and more than one?). Below is the actual MFT Record. and screenshot. How do we create such record in MFT with mklink tool?
0x46, 0x49, 0x4c, 0x45, 0x30, 0x00, 0x03, 0x00, 0xe3, 0xaf, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x02, 0x00, 0x38, 0x00, 0x03, 0x00, 0x88, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x6c, 0x00, 0x00,
0x02, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0xe8, 0xe7, 0x87, 0xf8, 0x0a, 0xbb, 0xd0, 0x01, 0xe8, 0xe7, 0x87, 0xf8, 0x0a, 0xbb, 0xd0, 0x01,
0xab, 0xe1, 0xdc, 0x00, 0x89, 0x5e, 0xd1, 0x01, 0xe8, 0xe7, 0x87, 0xf8, 0x0a, 0xbb, 0xd0, 0x01,
0x06, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x73, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00,
0x95, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xab, 0xe1, 0xdc, 0x00, 0x89, 0x5e, 0xd1, 0x01,
0xab, 0xe1, 0xdc, 0x00, 0x89, 0x5e, 0xd1, 0x01, 0xab, 0xe1, 0xdc, 0x00, 0x89, 0x5e, 0xd1, 0x01,
0xab, 0xe1, 0xdc, 0x00, 0x89, 0x5e, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x0e, 0x01, 0x4c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x53, 0x00,
0x65, 0x00, 0x74, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x73, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
0x52, 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x95, 0x05, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0xe8, 0xe7, 0x87, 0xf8, 0x0a, 0xbb, 0xd0, 0x01, 0xe8, 0xe7, 0x87, 0xf8, 0x0a, 0xbb, 0xd0, 0x01,
0xab, 0xe1, 0xdc, 0x00, 0x89, 0x5e, 0xd1, 0x01, 0xe8, 0xe7, 0x87, 0xf8, 0x0a, 0xbb, 0xd0, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x06, 0x24, 0x00, 0x10, 0x03, 0x00, 0x00, 0xa0, 0x08, 0x02, 0x4c, 0x00, 0x4f, 0x00, 0x43, 0x00,
0x41, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x7e, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x90, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x24, 0x00, 0x49, 0x00, 0x33, 0x00, 0x30, 0x00,
0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0xc0, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
0x94, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xa0, 0x8c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x44, 0x00, 0x46, 0x00, 0x3c, 0x00, 0x5c, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x02, 0x00,
0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00,
0x5c, 0x00, 0x44, 0x00, 0x65, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x74, 0x00,
0x5c, 0x00, 0x41, 0x00, 0x70, 0x00, 0x70, 0x00, 0x44, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00,
0x5c, 0x00, 0x4c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x43, 0x00,
0x3a, 0x00, 0x5c, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x5c, 0x00,
0x44, 0x00, 0x65, 0x00, 0x66, 0x00, 0x61, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x5c, 0x00,
0x41, 0x00, 0x70, 0x00, 0x70, 0x00, 0x44, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x5c, 0x00,
0x4c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x82, 0x79, 0x47, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
These are hard links corresponding to 8.3 file naming convention. If you look closely, every directory entries with reparse attribute has a ~ symbol in its name. Also, you can see that the reparse attribute is only present in the second file name attribute.

Render pixel buffer with Cocoa

I've searched through various Apple's docs and StackOverflow answers, but nothing really helped, still have a blank app's window. I'm trying to display the content of a pixel buffer in the NSWindow, to do that I've allocated a buffer:
UInt8* row = (UInt8 *) malloc(WINDOW_WIDTH * WINDOW_HEIGHT * bytes_per_pixel);
UInt32 pitch = (WINDOW_WIDTH * bytes_per_pixel);
// For each row
for (UInt32 y = 0; y < WINDOW_HEIGHT; ++y) {
Pixel* pixel = (Pixel *) row;
// For each pixel in a row
for (UInt32 x = 0; x < WINDOW_WIDTH; ++x) {
*pixel++ = 0xFF000000;
}
row += pitch;
}
This should prepare a buffer with red pixels. Then I'm creating a NSBitmapImageRep:
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(u8 *) row
pixelsWide:WINDOW_WIDTH
pixelsHigh:WINDOW_HEIGHT
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:WINDOW_WIDTH * 4
bitsPerPixel:32];
Which then converted into NSImage:
NSSize imageSize = NSMakeSize(CGImageGetWidth([imageRep CGImage]), CGImageGetHeight([imageRep CGImage]));
NSImage *image = [[NSImage alloc] initWithSize:imageSize];
[image addRepresentation:imageRep];
Then I'm configuring the view:
NSView *view = [window contentView];
[view setWantsLayer: YES];
[[view layer] setContents: image];
Sadly this doesn't give me the result I expect.
Here are some problems with your code:
You are incrementing row by pitch at the end of each y-loop. You never saved the pointer to the beginning of the buffer. When you create your NSBitmapImageRep, you pass a pointer that is past the end of the buffer.
You are passing row as the first (planes) argument of initWithBitmapDataPlanes:..., but you need to pass &row. The documentation says
An array of character pointers, each of which points to a buffer containing raw image data.[…]
An “array of character pointers” means (in C) you pass a pointer to a pointer.
You say “This should prepare a buffer with red pixels.” But you filled the buffer with 0xFF000000, and you said hasAlpha:YES. Depending on the byte order used by the initializer, either you have set the alpha channel to 0, or you have set the alpha channel to 0xFF but set all of the color channels to 0.
As it happens, you have set each pixel to opaque black (alpha = 0xFF, colors all zero). Try setting each pixel to 0xFF00007F and you'll get a dimmed red (alpha = 0xFF, red = 0x7F).
Thus:
typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha;
} Pixel;
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
size_t width = self.window.contentView.bounds.size.width;
size_t height = self.window.contentView.bounds.size.height;
Pixel color = { .red=127, .green=0, .blue=0, .alpha=255 };
size_t pitch = width * sizeof(Pixel);
uint8_t *buffer = malloc(pitch * height);
for (size_t y = 0; y < height; ++y) {
Pixel *row = (Pixel *)(buffer + y * pitch);
for (size_t x = 0; x < width; ++x) {
row[x] = color;
}
}
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&buffer
pixelsWide:width pixelsHigh:height
bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:pitch bitsPerPixel:sizeof(Pixel) * 8];
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
[image addRepresentation:rep];
self.window.contentView.wantsLayer = YES;
self.window.contentView.layer.contents = image;
}
#end
Result:
Note that I didn't free buffer. If you free buffer before rep is destroyed, things will go wrong. For example, if you just add free(buffer) to the end of applicationDidFinishLaunching:, the window appears gray.
This is a thorny problem to solve. If you use Core Graphics instead, the memory management is all handled properly. You can ask Core Graphics to allocate the buffer for you (by passing NULL instead of a valid pointer), and it will free the buffer when appropriate.
You have to release the Core Graphics objects you create to avoid memory leaks, but you can do that as soon as you're done with them. The Product > Analyze command can also help you find leaks of Core Graphics objects, but will not help you find leaks of un-freed malloc blocks.
Here's what a Core Graphics solution looks like:
typedef struct {
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha;
} Pixel;
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
size_t width = self.window.contentView.bounds.size.width;
size_t height = self.window.contentView.bounds.size.height;
CGColorSpaceRef rgb = CGColorSpaceCreateWithName(kCGColorSpaceLinearSRGB);
CGContextRef gc = CGBitmapContextCreate(NULL, width, height, 8, 0, rgb, kCGImageByteOrder32Big | kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(rgb);
size_t pitch = CGBitmapContextGetBytesPerRow(gc);
uint8_t *buffer = CGBitmapContextGetData(gc);
Pixel color = { .red=127, .green=0, .blue=0, .alpha=255 };
for (size_t y = 0; y < height; ++y) {
Pixel *row = (Pixel *)(buffer + y * pitch);
for (size_t x = 0; x < width; ++x) {
row[x] = color;
}
}
CGImageRef image = CGBitmapContextCreateImage(gc);
CGContextRelease(gc);
self.window.contentView.wantsLayer = YES;
self.window.contentView.layer.contents = (__bridge id)image;
CGImageRelease(image);
}
#end
Note sure what's going on, but here's code that has been working for years:
static NSImage* NewImageFromRGBA( const UInt8* rawRGBA, NSInteger width, NSInteger height )
{
size_t rawRGBASize = height*width*4/* sizeof(RGBA) = 4 */;
// Create a bitmap representation, allowing NSBitmapImageRep to allocate its own data buffer
NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bytesPerRow:0
bitsPerPixel:0];
NSCAssert(imageRep!=nil,#"failed to create NSBitmapImageRep");
NSCAssert((size_t)[imageRep bytesPerPlane]==rawRGBASize,#"alignment or size of CGContext buffer and NSImageRep do not agree");
// Copy the raw bitmap image into the new image representation
memcpy([imageRep bitmapData],rawRGBA,rawRGBASize);
// Create an empty NSImage then add the bitmap representation to it
NSImage* image = [[NSImage alloc] initWithSize:NSMakeSize(width,height)];
[image addRepresentation:imageRep];
return image;
}

OpenGL draws nothing on Mac, Objective-C

I'm trying to draw something using OpenGL with VAO and VBO objects. To do that, I just subclassed NSOpenGLView. By default, OpenGL v2.1 was used, so, I put a PixelFormat, wrote code, and solved all the printed errors. For now the app is running well, but nothing is drawing at the window, even glClearColor has no effect. Please, help me to find and solve the problems. My OS is Mac v10.12 with OpenGL v4.1.
MyOpenGLView.m, part 1:
#import "MyOpenGLView.h"
#include <OpenGL/gl3.h>
#include "error.h"
static const char *vertexShaderSource =
"#version 410\n"
"in vec3 posAttr;\n"
"in vec3 colAttr;\n"
"out vec3 col;\n"
"void main() {\n"
" col = colAttr;\n"
" gl_Position.xyz = posAttr;\n"
" gl_Position.w = 1.0;\n"
" col = colAttr;\n"
"}\n";
static const char *fragmentShaderSource =
"#version 410\n"
"in vec3 col;\n"
"out vec4 color;\n"
"void main() {\n"
" color.rgb = col;\n"
" color.a = 1.0;\n"
//" color = vec4(1,1,1,1);\n"
"}\n";
// Shader properties
GLuint m_posAttr;
GLuint m_colAttr;
GLuint program;
// Arrays of positions and colors
float fTriangle[9];
float fTriangleColor[9];
// Low-level VBOs and VBAs
GLuint uiVBO[2];
GLuint uiVAO[1];
GLuint makeShader(GLenum type, const char *source) {
GLuint shader;
shader = glCreateShader(type);
GetError();
glShaderSource(shader, 1, &source, NULL);
GetError();
glCompileShader(shader);
GetError();
#if defined(DEBUG)
GLint logLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
GetError();
if (logLength > 0) {
GLchar *log = malloc((size_t)logLength);
glGetShaderInfoLog(shader, logLength, &logLength, log);
GetError();
NSLog(#"Shader compilation failed with error:\n%s", log);
free(log);
}
#endif
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
GetError();
if (0 == status) {
glDeleteShader(shader);
GetError();
NSLog(#"Shader compilation failed from code!");
assert(0);
}
return shader;
}
MyOpenGLView.m, part 2:
//// General staff
#implementation MyOpenGLView
- (void)awakeFromNib {
// Positions and colors of figures
fTriangle[0] = -0.4f; fTriangle[1] = 0.1f; fTriangle[2] = 0.0f;
fTriangle[3] = 0.4f; fTriangle[4] = 0.1f; fTriangle[5] = 0.0f;
fTriangle[6] = 0.0f; fTriangle[7] = 0.7f; fTriangle[8] = 0.0f;
fTriangleColor[0] = 1.0f; fTriangleColor[1] = 0.0f; fTriangleColor[2] = 0.0f;
fTriangleColor[3] = 0.0f; fTriangleColor[4] = 1.0f; fTriangleColor[5] = 0.0f;
fTriangleColor[6] = 0.0f; fTriangleColor[7] = 0.0f; fTriangleColor[8] = 1.0f;
NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, 24,
NSOpenGLPFAOpenGLProfile,
NSOpenGLProfileVersion4_1Core,
0
};
NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
if (!pf) {
NSLog(#"No OpenGL pixel format");
}
NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:nil];
[self setPixelFormat:pf];
[self setOpenGLContext:context];
NSLog(#"%s", glGetString(GL_VERSION));
GetError();
GLuint vertexShader = makeShader(GL_VERTEX_SHADER, vertexShaderSource);
GLuint fragmentShader = makeShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
program = glCreateProgram();
GetError();
glAttachShader(program, vertexShader);
GetError();
glAttachShader(program, fragmentShader);
GetError();
glLinkProgram(program);
GetError();
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
GetError();
if (0 == status) {
NSLog(#"Failed to link shader program");
assert( 0 );
}
m_posAttr = glGetAttribLocation(program, "posAttr");
GetError();
m_colAttr = glGetAttribLocation(program, "colAttr");
GetError();
glGenVertexArrays(1, &uiVAO[0]);
glGenBuffers(2, &uiVBO[0]);
GetError();
}
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
GetError();
glBindVertexArray(uiVAO[0]);
GetError();
glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), fTriangle, GL_STATIC_DRAW);
glEnableVertexAttribArray(m_posAttr);
GetError();
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
GetError();
glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]);
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), fTriangleColor, GL_STATIC_DRAW);
glEnableVertexAttribArray(m_colAttr);
GetError();
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
GetError();
glDrawArrays(GL_TRIANGLES, 0, 3);
GetError();
glDisableVertexAttribArray(m_posAttr);
glDisableVertexAttribArray(m_colAttr);
glFlush();
GetError();
}
- (void)dealloc {
glDeleteProgram(program);
glDeleteBuffers(2, uiVBO);
glDeleteVertexArrays(1, uiVAO);
GetError();
}
#end
error.h:
//// Prints OpenGL errors
#ifndef __ERROR_H__
#define __ERROR_H__
#include <stdlib.h>
#include <assert.h>
#ifdef DEBUG
#define GetError( )\
{\
for ( GLenum Error = glGetError( ); ( GL_NO_ERROR != Error ); Error = glGetError( ) )\
{\
switch ( Error )\
{\
case GL_INVALID_ENUM: printf( "\n%s\n\n", "GL_INVALID_ENUM" ); assert( 0 ); break;\
case GL_INVALID_VALUE: printf( "\n%s\n\n", "GL_INVALID_VALUE" ); assert( 0 ); break;\
case GL_INVALID_OPERATION: printf( "\n%s\n\n", "GL_INVALID_OPERATION" ); assert( 0 ); break;\
case GL_OUT_OF_MEMORY: printf( "\n%s\n\n", "GL_OUT_OF_MEMORY" ); assert( 0 ); break;\
default: break;\
}\
}\
}
#else
#define GetError( )
#endif /* DEBUG */
#endif /* __ERROR_H__ */
After lots of effort and code's modifications I figured it out: the only real problem was with NSOpenGLPFADoubleBuffer option in NSOpenGLPixelFormatAttribute array. After commenting this option I got the desired output.
To my mind, the reason is that I had 2 output graphical buffers. However, the code was executed a single time, 1st buffer was painted and then swapped. So, the 2nd buffer, which is empty, was drawn.

OpenTK GL.DrawElements is never called

I found this C++ code here. It draws simple rectangle. Works great.
#define GLEW_STATIC
#include <iostream>
#include <glew.h>
#include <freeglut.h>
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"in vec3 color;"
"out vec3 Color;"
"void main() {"
" Color = color;"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"in vec3 Color;"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(Color, 1.0);"
"}";
void Display()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glFlush();
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_MULTISAMPLE);
glutInitWindowSize(800, 600);
glutInitContextVersion(4, 4);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutCreateWindow("OpenGL");
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit())
exit(1);
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f // Bottom-left
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
glutDisplayFunc(Display);
glutMainLoop();
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
}
So I decided to rewrite it on C# with OpenTK framework:
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.IO;
namespace OpenTKTest
{
public class Game : GameWindow
{
private Int32 vao;
private Int32 vbo;
private Int32 ebo;
private Int32 vertexShader;
private Int32 fragmentShader;
private Int32 shaderProgram;
public Game() : base()
{
}
[STAThread]
public static void Main()
{
var window = new Game();
window.Run(120, 120);
window.Dispose();
}
protected override void OnLoad(EventArgs e)
{
GL.GenVertexArrays(1, out vao);
GL.BindVertexArray(vao);
GL.GenBuffers(1, out vbo);
var vertices = new Single[]
{
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Top-left
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, // Top-right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, // Bottom-right
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f // Bottom-left
};
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(sizeof(Single) * vertices.Length), vertices, BufferUsageHint.StaticDraw);
GL.GenBuffers(1, out ebo);
var elements = new Single[]
{
0, 1, 2,
2, 3, 0
};
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo);
GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(UInt32) * elements.Length), elements, BufferUsageHint.StaticDraw);
vertexShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertexShader, File.ReadAllText("vs.glsl"));
GL.CompileShader(vertexShader);
Console.WriteLine(GL.GetShaderInfoLog(vertexShader));
fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragmentShader, File.ReadAllText("fs.glsl"));
GL.CompileShader(fragmentShader);
Console.WriteLine(GL.GetShaderInfoLog(fragmentShader));
shaderProgram = GL.CreateProgram();
GL.AttachShader(shaderProgram, vertexShader);
GL.AttachShader(shaderProgram, fragmentShader);
GL.BindFragDataLocation(shaderProgram, 0, "outColor");
GL.LinkProgram(shaderProgram);
GL.UseProgram(shaderProgram);
var posAttrib = GL.GetAttribLocation(shaderProgram, "position");
GL.EnableVertexAttribArray(posAttrib);
GL.VertexAttribPointer(posAttrib, 2, VertexAttribPointerType.Float, false, 5 * sizeof(Single), IntPtr.Zero);
var colAttrib = GL.GetAttribLocation(shaderProgram, "color");
GL.EnableVertexAttribArray(colAttrib);
GL.VertexAttribPointer(colAttrib, 3, VertexAttribPointerType.Float, false, 5 * sizeof(Single), new IntPtr(2 * sizeof(Single)));
GL.Viewport(0, 0, Width, Height);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, IntPtr.Zero);
GL.Flush();
SwapBuffers();
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
GL.DeleteProgram(shaderProgram);
GL.DeleteShader(fragmentShader);
GL.DeleteShader(vertexShader);
GL.DeleteBuffers(1, ref ebo);
GL.DeleteBuffers(1, ref vbo);
GL.DeleteVertexArrays(1, ref vao);
}
}
}
Vertex shader:
#version 150 core
in vec2 position;
in vec3 color;
out vec3 Color;
void main()
{
Color = color;
gl_Position = vec4(position, 0.0, 1.0);
}
Fragment shader:
#version 150 core
in vec3 Color;
out vec4 outColor;
void main()
{
outColor = vec4(Color, 1.0);
}
Both sources are almost identical. But in C# version GL.DrawElements function is never called (I found it out while debugging with gDEBugger from gremedy).
Why this code doesn't work in OpenTK?

Cocoa and OpenGL teapot not drawn correctly

I mixed Cocoa, GLUT and OpenGL frameworks to draw a teapot.
I usually do this in plain C but I need to mix up Cocoa buttons and stuffs with OpenGL, this is the corrispettive C code:
#import <OpenGL/OpenGL.h>
#import <GLUT/GLUT.h>
#import <math.h>
#include "utility.h"
GLuint width=640, height=480;
GLfloat angle=0.0;
void init()
{
glEnable(GL_DEPTH_TEST);
glViewport(-500, -500, 1000, 1000);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, width/(float)height, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -100, 0, 0, 0, 0, 1, 0);
// Luci
glShadeModel(GL_FLAT);
glLightfv(GL_LIGHT0, GL_AMBIENT, (const GLfloat[]) {0,0,0} );
glLightfv(GL_LIGHT0, GL_DIFFUSE, (const GLfloat[]) {1,1,0} );
glLightfv(GL_LIGHT0, GL_SPECULAR, (const GLfloat[]) {0.5,0.5,0} );
glMaterialfv(GL_FRONT, GL_AMBIENT, (const GLfloat[]) {1,0,0} );
glMaterialfv(GL_FRONT, GL_DIFFUSE, (const GLfloat[]) {1,0.25,0} );
glMaterialfv(GL_FRONT, GL_SPECULAR, (const GLfloat[]) {1,0.75,0} );
glMaterialfv(GL_FRONT, GL_SHININESS, (const GLfloat[]) {1,1,0} );
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
}
void display()
{
glClearColor(BLACK);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(angle, 0, 1, 0);
glutSolidTeapot(10);
glPopMatrix();
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
if(key=='+')
{
angle+=5.0;
}
else if(key=='-')
{
angle-=5.0;
}
else
{
return;
}
makeRound(&angle);
glutPostRedisplay();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(width, height);
glutCreateWindow(argv[0]);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();
return 0;
}
And this is the result:
Then I'm subclassing a NSOpenGLView and do the same of this C code, just with different sizes, but the meterials and lights are the same:
#implementation MyView
#synthesize angle;
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
}
return self;
}
- (void) prepareOpenGL
{
NSOpenGLContext* context= self.openGLContext;
GLfloat width= self.bounds.size.width;
GLfloat height= self.bounds.size.height;
[context makeCurrentContext];
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, width/height, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -100, 0, 0, 0, 0, 1, 0);
// Lighting
glShadeModel(GL_FLAT);
glLightfv(GL_LIGHT0, GL_AMBIENT, (const GLfloat[]) {0,0,0} );
glLightfv(GL_LIGHT0, GL_DIFFUSE, (const GLfloat[]) {1,1,0} );
glLightfv(GL_LIGHT0, GL_SPECULAR, (const GLfloat[]) {0.5,0.5,0} );
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (const GLfloat[]) {1,0,0} );
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (const GLfloat[]) {1,0.25,0} );
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (const GLfloat[]) {1,0.75,0} );
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, (const GLfloat[]) {1,1,0} );
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
}
- (void)drawRect:(NSRect)dirtyRect
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(angle, 0, 1, 0);
glutSolidTeapot(20);
glPopMatrix();
glFlush();
}
#pragma mark - Actions
- (IBAction) increaseAngle :(id)sender
{
angle+=5.0;
if(angle>360.0)
{
angle-=360.0;
}
[self setNeedsDisplay: YES];
}
- (IBAction) decreaseAngle:(id)sender
{
angle-=5.0;
if(angle<0.0)
{
angle+=360.0;
}
[self setNeedsDisplay: YES];
}
#end
And this is the result:
That's pretty ugly and considering that I used the same meterials and lights, I think that I'm doing something wrong in the one done with Cocoa and OpenGL mixed.
Make sure you request a depth buffer when you create your GL context. You may not get one by default.